PageRenderTime 43ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/ntp-4.2.6p5/ntpd/refclock_parse.c

#
C | 6158 lines | 5120 code | 326 blank | 712 comment | 147 complexity | 7da9ac33c84e1bc9693c191d86bdcc5b MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, LGPL-3.0
  1. /*
  2. * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A
  3. *
  4. * refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A
  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-2009 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. # include "refclock_atom.h"
  131. #endif
  132. #ifdef PPS
  133. # ifdef HAVE_SYS_PPSCLOCK_H
  134. # include <sys/ppsclock.h>
  135. # endif
  136. # ifdef HAVE_TIO_SERIAL_STUFF
  137. # include <linux/serial.h>
  138. # endif
  139. #endif
  140. #define BUFFER_SIZE(_BUF, _PTR) ((_BUF) + sizeof(_BUF) - (_PTR))
  141. #define BUFFER_SIZES(_BUF, _PTR, _SZ) ((_BUF) + (_SZ) - (_PTR))
  142. /*
  143. * document type of PPS interfacing - copy of ifdef mechanism in local_input()
  144. */
  145. #undef PPS_METHOD
  146. #ifdef HAVE_PPSAPI
  147. #define PPS_METHOD "PPS API"
  148. #else
  149. #ifdef TIOCDCDTIMESTAMP
  150. #define PPS_METHOD "TIOCDCDTIMESTAMP"
  151. #else /* TIOCDCDTIMESTAMP */
  152. #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
  153. #ifdef HAVE_CIOGETEV
  154. #define PPS_METHOD "CIOGETEV"
  155. #endif
  156. #ifdef HAVE_TIOCGPPSEV
  157. #define PPS_METHOD "TIOCGPPSEV"
  158. #endif
  159. #endif
  160. #endif /* TIOCDCDTIMESTAMP */
  161. #endif /* HAVE_PPSAPI */
  162. #include "ntp_io.h"
  163. #include "ntp_stdlib.h"
  164. #include "parse.h"
  165. #include "mbg_gps166.h"
  166. #include "trimble.h"
  167. #include "binio.h"
  168. #include "ascii.h"
  169. #include "ieee754io.h"
  170. #include "recvbuff.h"
  171. static char rcsid[] = "refclock_parse.c,v 4.81 2009/05/01 10:15:29 kardel RELEASE_20090105_A+POWERUPTRUST";
  172. /**===========================================================================
  173. ** external interface to ntp mechanism
  174. **/
  175. static int parse_start (int, struct peer *);
  176. static void parse_shutdown (int, struct peer *);
  177. static void parse_poll (int, struct peer *);
  178. static void parse_control (int, struct refclockstat *, struct refclockstat *, struct peer *);
  179. struct refclock refclock_parse = {
  180. parse_start,
  181. parse_shutdown,
  182. parse_poll,
  183. parse_control,
  184. noentry,
  185. noentry,
  186. NOFLAGS
  187. };
  188. /*
  189. * Definitions
  190. */
  191. #define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
  192. #define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
  193. #define PARSEPPSDEVICE "/dev/refclockpps-%d" /* optional pps device to open %d is unit number */
  194. #undef ABS
  195. #define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))
  196. #define PARSE_HARDPPS_DISABLE 0
  197. #define PARSE_HARDPPS_ENABLE 1
  198. /**===========================================================================
  199. ** function vector for dynamically binding io handling mechanism
  200. **/
  201. struct parseunit; /* to keep inquiring minds happy */
  202. typedef struct bind
  203. {
  204. const char *bd_description; /* name of type of binding */
  205. int (*bd_init) (struct parseunit *); /* initialize */
  206. void (*bd_end) (struct parseunit *); /* end */
  207. int (*bd_setcs) (struct parseunit *, parsectl_t *); /* set character size */
  208. int (*bd_disable) (struct parseunit *); /* disable */
  209. int (*bd_enable) (struct parseunit *); /* enable */
  210. int (*bd_getfmt) (struct parseunit *, parsectl_t *); /* get format */
  211. int (*bd_setfmt) (struct parseunit *, parsectl_t *); /* setfmt */
  212. int (*bd_timecode) (struct parseunit *, parsectl_t *); /* get time code */
  213. void (*bd_receive) (struct recvbuf *); /* receive operation */
  214. int (*bd_io_input) (struct recvbuf *); /* input operation */
  215. } bind_t;
  216. #define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)
  217. #define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_)
  218. #define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_)
  219. #define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_)
  220. #define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_)
  221. #define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_)
  222. #define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
  223. /*
  224. * special handling flags
  225. */
  226. #define PARSE_F_PPSONSECOND 0x00000001 /* PPS pulses are on second */
  227. #define PARSE_F_POWERUPTRUST 0x00000100 /* POWERUP state ist trusted for */
  228. /* trusttime after SYNC was seen */
  229. /**===========================================================================
  230. ** error message regression handling
  231. **
  232. ** there are quite a few errors that can occur in rapid succession such as
  233. ** noisy input data or no data at all. in order to reduce the amount of
  234. ** syslog messages in such case, we are using a backoff algorithm. We limit
  235. ** the number of error messages of a certain class to 1 per time unit. if a
  236. ** configurable number of messages is displayed that way, we move on to the
  237. ** next time unit / count for that class. a count of messages that have been
  238. ** suppressed is held and displayed whenever a corresponding message is
  239. ** displayed. the time units for a message class will also be displayed.
  240. ** whenever an error condition clears we reset the error message state,
  241. ** thus we would still generate much output on pathological conditions
  242. ** where the system oscillates between OK and NOT OK states. coping
  243. ** with that condition is currently considered too complicated.
  244. **/
  245. #define ERR_ALL (unsigned)~0 /* "all" errors */
  246. #define ERR_BADDATA (unsigned)0 /* unusable input data/conversion errors */
  247. #define ERR_NODATA (unsigned)1 /* no input data */
  248. #define ERR_BADIO (unsigned)2 /* read/write/select errors */
  249. #define ERR_BADSTATUS (unsigned)3 /* unsync states */
  250. #define ERR_BADEVENT (unsigned)4 /* non nominal events */
  251. #define ERR_INTERNAL (unsigned)5 /* internal error */
  252. #define ERR_CNT (unsigned)(ERR_INTERNAL+1)
  253. #define ERR(_X_) if (list_err(parse, (_X_)))
  254. struct errorregression
  255. {
  256. u_long err_count; /* number of repititions per class */
  257. u_long err_delay; /* minimum delay between messages */
  258. };
  259. static struct errorregression
  260. err_baddata[] = /* error messages for bad input data */
  261. {
  262. { 1, 0 }, /* output first message immediately */
  263. { 5, 60 }, /* output next five messages in 60 second intervals */
  264. { 3, 3600 }, /* output next 3 messages in hour intervals */
  265. { 0, 12*3600 } /* repeat messages only every 12 hours */
  266. };
  267. static struct errorregression
  268. err_nodata[] = /* error messages for missing input data */
  269. {
  270. { 1, 0 }, /* output first message immediately */
  271. { 5, 60 }, /* output next five messages in 60 second intervals */
  272. { 3, 3600 }, /* output next 3 messages in hour intervals */
  273. { 0, 12*3600 } /* repeat messages only every 12 hours */
  274. };
  275. static struct errorregression
  276. err_badstatus[] = /* unsynchronized state messages */
  277. {
  278. { 1, 0 }, /* output first message immediately */
  279. { 5, 60 }, /* output next five messages in 60 second intervals */
  280. { 3, 3600 }, /* output next 3 messages in hour intervals */
  281. { 0, 12*3600 } /* repeat messages only every 12 hours */
  282. };
  283. static struct errorregression
  284. err_badio[] = /* io failures (bad reads, selects, ...) */
  285. {
  286. { 1, 0 }, /* output first message immediately */
  287. { 5, 60 }, /* output next five messages in 60 second intervals */
  288. { 5, 3600 }, /* output next 3 messages in hour intervals */
  289. { 0, 12*3600 } /* repeat messages only every 12 hours */
  290. };
  291. static struct errorregression
  292. err_badevent[] = /* non nominal events */
  293. {
  294. { 20, 0 }, /* output first message immediately */
  295. { 6, 60 }, /* output next five messages in 60 second intervals */
  296. { 5, 3600 }, /* output next 3 messages in hour intervals */
  297. { 0, 12*3600 } /* repeat messages only every 12 hours */
  298. };
  299. static struct errorregression
  300. err_internal[] = /* really bad things - basically coding/OS errors */
  301. {
  302. { 0, 0 }, /* output all messages immediately */
  303. };
  304. static struct errorregression *
  305. err_tbl[] =
  306. {
  307. err_baddata,
  308. err_nodata,
  309. err_badio,
  310. err_badstatus,
  311. err_badevent,
  312. err_internal
  313. };
  314. struct errorinfo
  315. {
  316. u_long err_started; /* begin time (ntp) of error condition */
  317. u_long err_last; /* last time (ntp) error occurred */
  318. u_long err_cnt; /* number of error repititions */
  319. u_long err_suppressed; /* number of suppressed messages */
  320. struct errorregression *err_stage; /* current error stage */
  321. };
  322. /**===========================================================================
  323. ** refclock instance data
  324. **/
  325. struct parseunit
  326. {
  327. /*
  328. * NTP management
  329. */
  330. struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */
  331. struct refclockproc *generic; /* backlink to refclockproc structure */
  332. /*
  333. * PARSE io
  334. */
  335. bind_t *binding; /* io handling binding */
  336. /*
  337. * parse state
  338. */
  339. parse_t parseio; /* io handling structure (user level parsing) */
  340. /*
  341. * type specific parameters
  342. */
  343. struct parse_clockinfo *parse_type; /* link to clock description */
  344. /*
  345. * clock state handling/reporting
  346. */
  347. u_char flags; /* flags (leap_control) */
  348. u_long lastchange; /* time (ntp) when last state change accured */
  349. u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
  350. u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */
  351. u_short lastformat; /* last format used */
  352. u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */
  353. u_long maxunsync; /* max time in seconds a receiver is trusted after loosing synchronisation */
  354. double ppsphaseadjust; /* phase adjustment of PPS time stamp */
  355. u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */
  356. u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
  357. int ppsfd; /* fd to ise for PPS io */
  358. #ifdef HAVE_PPSAPI
  359. int hardppsstate; /* current hard pps state */
  360. struct refclock_atom atom; /* PPSAPI structure */
  361. #endif
  362. parsetime_t timedata; /* last (parse module) data */
  363. void *localdata; /* optional local, receiver-specific data */
  364. unsigned long localstate; /* private local state */
  365. struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */
  366. struct ctl_var *kv; /* additional pseudo variables */
  367. u_long laststatistic; /* time when staticstics where output */
  368. };
  369. /**===========================================================================
  370. ** Clockinfo section all parameter for specific clock types
  371. ** includes NTP parameters, TTY parameters and IO handling parameters
  372. **/
  373. static void poll_dpoll (struct parseunit *);
  374. static void poll_poll (struct peer *);
  375. static int poll_init (struct parseunit *);
  376. typedef struct poll_info
  377. {
  378. u_long rate; /* poll rate - once every "rate" seconds - 0 off */
  379. const char *string; /* string to send for polling */
  380. u_long count; /* number of characters in string */
  381. } poll_info_t;
  382. #define NO_CL_FLAGS 0
  383. #define NO_POLL 0
  384. #define NO_INIT 0
  385. #define NO_END 0
  386. #define NO_EVENT 0
  387. #define NO_LCLDATA 0
  388. #define NO_MESSAGE 0
  389. #define NO_PPSDELAY 0
  390. #define DCF_ID "DCF" /* generic DCF */
  391. #define DCF_A_ID "DCFa" /* AM demodulation */
  392. #define DCF_P_ID "DCFp" /* psuedo random phase shift */
  393. #define GPS_ID "GPS" /* GPS receiver */
  394. #define NOCLOCK_ROOTDELAY 0.0
  395. #define NOCLOCK_BASEDELAY 0.0
  396. #define NOCLOCK_DESCRIPTION 0
  397. #define NOCLOCK_MAXUNSYNC 0
  398. #define NOCLOCK_CFLAG 0
  399. #define NOCLOCK_IFLAG 0
  400. #define NOCLOCK_OFLAG 0
  401. #define NOCLOCK_LFLAG 0
  402. #define NOCLOCK_ID "TILT"
  403. #define NOCLOCK_POLL NO_POLL
  404. #define NOCLOCK_INIT NO_INIT
  405. #define NOCLOCK_END NO_END
  406. #define NOCLOCK_DATA NO_LCLDATA
  407. #define NOCLOCK_FORMAT ""
  408. #define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
  409. #define NOCLOCK_SAMPLES 0
  410. #define NOCLOCK_KEEP 0
  411. #define DCF_TYPE CTL_SST_TS_LF
  412. #define GPS_TYPE CTL_SST_TS_UHF
  413. /*
  414. * receiver specific constants
  415. */
  416. #define MBG_SPEED (B9600)
  417. #define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB)
  418. #define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
  419. #define MBG_OFLAG 0
  420. #define MBG_LFLAG 0
  421. #define MBG_FLAGS PARSE_F_PPSONSECOND
  422. /*
  423. * Meinberg DCF77 receivers
  424. */
  425. #define DCFUA31_ROOTDELAY 0.0 /* 0 */
  426. #define DCFUA31_BASEDELAY 0.010 /* 10.7421875ms: 10 ms (+/- 3 ms) */
  427. #define DCFUA31_DESCRIPTION "Meinberg DCF77 C51 or compatible"
  428. #define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */
  429. #define DCFUA31_SPEED MBG_SPEED
  430. #define DCFUA31_CFLAG MBG_CFLAG
  431. #define DCFUA31_IFLAG MBG_IFLAG
  432. #define DCFUA31_OFLAG MBG_OFLAG
  433. #define DCFUA31_LFLAG MBG_LFLAG
  434. #define DCFUA31_SAMPLES 5
  435. #define DCFUA31_KEEP 3
  436. #define DCFUA31_FORMAT "Meinberg Standard"
  437. /*
  438. * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
  439. */
  440. #define DCFPZF535_ROOTDELAY 0.0
  441. #define DCFPZF535_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
  442. #define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/509 / TCXO"
  443. #define DCFPZF535_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours
  444. * @ 5e-8df/f we have accumulated
  445. * at most 2.16 ms (thus we move to
  446. * NTP synchronisation */
  447. #define DCFPZF535_SPEED MBG_SPEED
  448. #define DCFPZF535_CFLAG MBG_CFLAG
  449. #define DCFPZF535_IFLAG MBG_IFLAG
  450. #define DCFPZF535_OFLAG MBG_OFLAG
  451. #define DCFPZF535_LFLAG MBG_LFLAG
  452. #define DCFPZF535_SAMPLES 5
  453. #define DCFPZF535_KEEP 3
  454. #define DCFPZF535_FORMAT "Meinberg Standard"
  455. /*
  456. * Meinberg DCF PZF535/OCXO receiver
  457. */
  458. #define DCFPZF535OCXO_ROOTDELAY 0.0
  459. #define DCFPZF535OCXO_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
  460. #define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/509 / OCXO"
  461. #define DCFPZF535OCXO_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
  462. * @ 5e-9df/f we have accumulated
  463. * at most an error of 1.73 ms
  464. * (thus we move to NTP synchronisation) */
  465. #define DCFPZF535OCXO_SPEED MBG_SPEED
  466. #define DCFPZF535OCXO_CFLAG MBG_CFLAG
  467. #define DCFPZF535OCXO_IFLAG MBG_IFLAG
  468. #define DCFPZF535OCXO_OFLAG MBG_OFLAG
  469. #define DCFPZF535OCXO_LFLAG MBG_LFLAG
  470. #define DCFPZF535OCXO_SAMPLES 5
  471. #define DCFPZF535OCXO_KEEP 3
  472. #define DCFPZF535OCXO_FORMAT "Meinberg Standard"
  473. /*
  474. * Meinberg GPS16X receiver
  475. */
  476. static void gps16x_message (struct parseunit *, parsetime_t *);
  477. static int gps16x_poll_init (struct parseunit *);
  478. #define GPS16X_ROOTDELAY 0.0 /* nothing here */
  479. #define GPS16X_BASEDELAY 0.001968 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
  480. #define GPS16X_DESCRIPTION "Meinberg GPS16x receiver"
  481. #define GPS16X_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
  482. * @ 5e-9df/f we have accumulated
  483. * at most an error of 1.73 ms
  484. * (thus we move to NTP synchronisation) */
  485. #define GPS16X_SPEED B19200
  486. #define GPS16X_CFLAG (CS8|CREAD|CLOCAL|HUPCL)
  487. #define GPS16X_IFLAG (IGNBRK|IGNPAR)
  488. #define GPS16X_OFLAG MBG_OFLAG
  489. #define GPS16X_LFLAG MBG_LFLAG
  490. #define GPS16X_POLLRATE 6
  491. #define GPS16X_POLLCMD ""
  492. #define GPS16X_CMDSIZE 0
  493. static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE };
  494. #define GPS16X_INIT gps16x_poll_init
  495. #define GPS16X_POLL 0
  496. #define GPS16X_END 0
  497. #define GPS16X_DATA ((void *)(&gps16x_pollinfo))
  498. #define GPS16X_MESSAGE gps16x_message
  499. #define GPS16X_ID GPS_ID
  500. #define GPS16X_FORMAT "Meinberg GPS Extended"
  501. #define GPS16X_SAMPLES 5
  502. #define GPS16X_KEEP 3
  503. /*
  504. * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
  505. *
  506. * This is really not the hottest clock - but before you have nothing ...
  507. */
  508. #define DCF7000_ROOTDELAY 0.0 /* 0 */
  509. #define DCF7000_BASEDELAY 0.405 /* slow blow */
  510. #define DCF7000_DESCRIPTION "ELV DCF7000"
  511. #define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */
  512. #define DCF7000_SPEED (B9600)
  513. #define DCF7000_CFLAG (CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
  514. #define DCF7000_IFLAG (IGNBRK)
  515. #define DCF7000_OFLAG 0
  516. #define DCF7000_LFLAG 0
  517. #define DCF7000_SAMPLES 5
  518. #define DCF7000_KEEP 3
  519. #define DCF7000_FORMAT "ELV DCF7000"
  520. /*
  521. * Schmid DCF Receiver Kit
  522. *
  523. * When the WSDCF clock is operating optimally we want the primary clock
  524. * distance to come out at 300 ms. Thus, peer.distance in the WSDCF peer
  525. * structure is set to 290 ms and we compute delays which are at least
  526. * 10 ms long. The following are 290 ms and 10 ms expressed in u_fp format
  527. */
  528. #define WS_POLLRATE 1 /* every second - watch interdependency with poll routine */
  529. #define WS_POLLCMD "\163"
  530. #define WS_CMDSIZE 1
  531. static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
  532. #define WSDCF_INIT poll_init
  533. #define WSDCF_POLL poll_dpoll
  534. #define WSDCF_END 0
  535. #define WSDCF_DATA ((void *)(&wsdcf_pollinfo))
  536. #define WSDCF_ROOTDELAY 0.0 /* 0 */
  537. #define WSDCF_BASEDELAY 0.010 /* ~ 10ms */
  538. #define WSDCF_DESCRIPTION "WS/DCF Receiver"
  539. #define WSDCF_FORMAT "Schmid"
  540. #define WSDCF_MAXUNSYNC (60*60) /* assume this beast hold at 1 h better than 2 ms XXX-must verify */
  541. #define WSDCF_SPEED (B1200)
  542. #define WSDCF_CFLAG (CS8|CREAD|CLOCAL)
  543. #define WSDCF_IFLAG 0
  544. #define WSDCF_OFLAG 0
  545. #define WSDCF_LFLAG 0
  546. #define WSDCF_SAMPLES 5
  547. #define WSDCF_KEEP 3
  548. /*
  549. * RAW DCF77 - input of DCF marks via RS232 - many variants
  550. */
  551. #define RAWDCF_FLAGS 0
  552. #define RAWDCF_ROOTDELAY 0.0 /* 0 */
  553. #define RAWDCF_BASEDELAY 0.258
  554. #define RAWDCF_FORMAT "RAW DCF77 Timecode"
  555. #define RAWDCF_MAXUNSYNC (0) /* sorry - its a true receiver - no signal - no time */
  556. #define RAWDCF_SPEED (B50)
  557. #ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined(SYS_IRIX5) */
  558. /* somehow doesn't grok PARENB & IGNPAR (mj) */
  559. # define RAWDCF_CFLAG (CS8|CREAD|CLOCAL)
  560. #else
  561. # define RAWDCF_CFLAG (CS8|CREAD|CLOCAL|PARENB)
  562. #endif
  563. #ifdef RAWDCF_NO_IGNPAR /* Was: defined(SYS_LINUX) && defined(CLOCK_RAWDCF) */
  564. # define RAWDCF_IFLAG 0
  565. #else
  566. # define RAWDCF_IFLAG (IGNPAR)
  567. #endif
  568. #define RAWDCF_OFLAG 0
  569. #define RAWDCF_LFLAG 0
  570. #define RAWDCF_SAMPLES 20
  571. #define RAWDCF_KEEP 12
  572. #define RAWDCF_INIT 0
  573. /*
  574. * RAW DCF variants
  575. */
  576. /*
  577. * Conrad receiver
  578. *
  579. * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad
  580. * (~40DM - roughly $30 ) followed by a level converter for RS232
  581. */
  582. #define CONRAD_BASEDELAY 0.292 /* Conrad receiver @ 50 Baud on a Sun */
  583. #define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
  584. /* Gude Analog- und Digitalsystem GmbH 'Expert mouseCLOCK USB v2.0' */
  585. #define GUDE_EMC_USB_V20_SPEED (B4800)
  586. #define GUDE_EMC_USB_V20_BASEDELAY 0.425 /* USB serial<->USB converter FTDI232R */
  587. #define GUDE_EMC_USB_V20_DESCRIPTION "RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)"
  588. /*
  589. * TimeBrick receiver
  590. */
  591. #define TIMEBRICK_BASEDELAY 0.210 /* TimeBrick @ 50 Baud on a Sun */
  592. #define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
  593. /*
  594. * IGEL:clock receiver
  595. */
  596. #define IGELCLOCK_BASEDELAY 0.258 /* IGEL:clock receiver */
  597. #define IGELCLOCK_DESCRIPTION "RAW DCF77 CODE (IGEL:clock)"
  598. #define IGELCLOCK_SPEED (B1200)
  599. #define IGELCLOCK_CFLAG (CS8|CREAD|HUPCL|CLOCAL)
  600. /*
  601. * RAWDCF receivers that need to be powered from DTR
  602. * (like Expert mouse clock)
  603. */
  604. static int rawdcf_init_1 (struct parseunit *);
  605. #define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)"
  606. #define RAWDCFDTRSET75_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR @ 75 baud)"
  607. #define RAWDCFDTRSET_INIT rawdcf_init_1
  608. /*
  609. * RAWDCF receivers that need to be powered from
  610. * DTR CLR and RTS SET
  611. */
  612. static int rawdcf_init_2 (struct parseunit *);
  613. #define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)"
  614. #define RAWDCFDTRCLRRTSSET75_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET @ 75 baud)"
  615. #define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2
  616. /*
  617. * Trimble GPS receivers (TAIP and TSIP protocols)
  618. */
  619. #ifndef TRIM_POLLRATE
  620. #define TRIM_POLLRATE 0 /* only true direct polling */
  621. #endif
  622. #define TRIM_TAIPPOLLCMD ">SRM;FR_FLAG=F;EC_FLAG=F<>QTM<"
  623. #define TRIM_TAIPCMDSIZE (sizeof(TRIM_TAIPPOLLCMD)-1)
  624. static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
  625. static int trimbletaip_init (struct parseunit *);
  626. static void trimbletaip_event (struct parseunit *, int);
  627. /* query time & UTC correction data */
  628. static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX };
  629. static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) };
  630. static int trimbletsip_init (struct parseunit *);
  631. static void trimbletsip_end (struct parseunit *);
  632. static void trimbletsip_message (struct parseunit *, parsetime_t *);
  633. static void trimbletsip_event (struct parseunit *, int);
  634. #define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */
  635. #define TRIMBLE_RESET_HOLDOFF TRIMBLETSIP_IDLE_TIME
  636. #define TRIMBLETAIP_SPEED (B4800)
  637. #define TRIMBLETAIP_CFLAG (CS8|CREAD|CLOCAL)
  638. #define TRIMBLETAIP_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
  639. #define TRIMBLETAIP_OFLAG (OPOST|ONLCR)
  640. #define TRIMBLETAIP_LFLAG (0)
  641. #define TRIMBLETSIP_SPEED (B9600)
  642. #define TRIMBLETSIP_CFLAG (CS8|CLOCAL|CREAD|PARENB|PARODD)
  643. #define TRIMBLETSIP_IFLAG (IGNBRK)
  644. #define TRIMBLETSIP_OFLAG (0)
  645. #define TRIMBLETSIP_LFLAG (ICANON)
  646. #define TRIMBLETSIP_SAMPLES 5
  647. #define TRIMBLETSIP_KEEP 3
  648. #define TRIMBLETAIP_SAMPLES 5
  649. #define TRIMBLETAIP_KEEP 3
  650. #define TRIMBLETAIP_FLAGS (PARSE_F_PPSONSECOND)
  651. #define TRIMBLETSIP_FLAGS (TRIMBLETAIP_FLAGS)
  652. #define TRIMBLETAIP_POLL poll_dpoll
  653. #define TRIMBLETSIP_POLL poll_dpoll
  654. #define TRIMBLETAIP_INIT trimbletaip_init
  655. #define TRIMBLETSIP_INIT trimbletsip_init
  656. #define TRIMBLETAIP_EVENT trimbletaip_event
  657. #define TRIMBLETSIP_EVENT trimbletsip_event
  658. #define TRIMBLETSIP_MESSAGE trimbletsip_message
  659. #define TRIMBLETAIP_END 0
  660. #define TRIMBLETSIP_END trimbletsip_end
  661. #define TRIMBLETAIP_DATA ((void *)(&trimbletaip_pollinfo))
  662. #define TRIMBLETSIP_DATA ((void *)(&trimbletsip_pollinfo))
  663. #define TRIMBLETAIP_ID GPS_ID
  664. #define TRIMBLETSIP_ID GPS_ID
  665. #define TRIMBLETAIP_FORMAT "Trimble TAIP"
  666. #define TRIMBLETSIP_FORMAT "Trimble TSIP"
  667. #define TRIMBLETAIP_ROOTDELAY 0x0
  668. #define TRIMBLETSIP_ROOTDELAY 0x0
  669. #define TRIMBLETAIP_BASEDELAY 0.0
  670. #define TRIMBLETSIP_BASEDELAY 0.020 /* GPS time message latency */
  671. #define TRIMBLETAIP_DESCRIPTION "Trimble GPS (TAIP) receiver"
  672. #define TRIMBLETSIP_DESCRIPTION "Trimble GPS (TSIP) receiver"
  673. #define TRIMBLETAIP_MAXUNSYNC 0
  674. #define TRIMBLETSIP_MAXUNSYNC 0
  675. #define TRIMBLETAIP_EOL '<'
  676. /*
  677. * RadioCode Clocks RCC 800 receiver
  678. */
  679. #define RCC_POLLRATE 0 /* only true direct polling */
  680. #define RCC_POLLCMD "\r"
  681. #define RCC_CMDSIZE 1
  682. static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE };
  683. #define RCC8000_FLAGS 0
  684. #define RCC8000_POLL poll_dpoll
  685. #define RCC8000_INIT poll_init
  686. #define RCC8000_END 0
  687. #define RCC8000_DATA ((void *)(&rcc8000_pollinfo))
  688. #define RCC8000_ROOTDELAY 0.0
  689. #define RCC8000_BASEDELAY 0.0
  690. #define RCC8000_ID "MSF"
  691. #define RCC8000_DESCRIPTION "RCC 8000 MSF Receiver"
  692. #define RCC8000_FORMAT "Radiocode RCC8000"
  693. #define RCC8000_MAXUNSYNC (60*60) /* should be ok for an hour */
  694. #define RCC8000_SPEED (B2400)
  695. #define RCC8000_CFLAG (CS8|CREAD|CLOCAL)
  696. #define RCC8000_IFLAG (IGNBRK|IGNPAR)
  697. #define RCC8000_OFLAG 0
  698. #define RCC8000_LFLAG 0
  699. #define RCC8000_SAMPLES 5
  700. #define RCC8000_KEEP 3
  701. /*
  702. * Hopf Radio clock 6021 Format
  703. *
  704. */
  705. #define HOPF6021_ROOTDELAY 0.0
  706. #define HOPF6021_BASEDELAY 0.0
  707. #define HOPF6021_DESCRIPTION "HOPF 6021"
  708. #define HOPF6021_FORMAT "hopf Funkuhr 6021"
  709. #define HOPF6021_MAXUNSYNC (60*60) /* should be ok for an hour */
  710. #define HOPF6021_SPEED (B9600)
  711. #define HOPF6021_CFLAG (CS8|CREAD|CLOCAL)
  712. #define HOPF6021_IFLAG (IGNBRK|ISTRIP)
  713. #define HOPF6021_OFLAG 0
  714. #define HOPF6021_LFLAG 0
  715. #define HOPF6021_FLAGS 0
  716. #define HOPF6021_SAMPLES 5
  717. #define HOPF6021_KEEP 3
  718. /*
  719. * Diem's Computime Radio Clock Receiver
  720. */
  721. #define COMPUTIME_FLAGS 0
  722. #define COMPUTIME_ROOTDELAY 0.0
  723. #define COMPUTIME_BASEDELAY 0.0
  724. #define COMPUTIME_ID DCF_ID
  725. #define COMPUTIME_DESCRIPTION "Diem's Computime receiver"
  726. #define COMPUTIME_FORMAT "Diem's Computime Radio Clock"
  727. #define COMPUTIME_TYPE DCF_TYPE
  728. #define COMPUTIME_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
  729. #define COMPUTIME_SPEED (B9600)
  730. #define COMPUTIME_CFLAG (CSTOPB|CS7|CREAD|CLOCAL)
  731. #define COMPUTIME_IFLAG (IGNBRK|IGNPAR|ISTRIP)
  732. #define COMPUTIME_OFLAG 0
  733. #define COMPUTIME_LFLAG 0
  734. #define COMPUTIME_SAMPLES 5
  735. #define COMPUTIME_KEEP 3
  736. /*
  737. * Varitext Radio Clock Receiver
  738. */
  739. #define VARITEXT_FLAGS 0
  740. #define VARITEXT_ROOTDELAY 0.0
  741. #define VARITEXT_BASEDELAY 0.0
  742. #define VARITEXT_ID "MSF"
  743. #define VARITEXT_DESCRIPTION "Varitext receiver"
  744. #define VARITEXT_FORMAT "Varitext Radio Clock"
  745. #define VARITEXT_TYPE DCF_TYPE
  746. #define VARITEXT_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
  747. #define VARITEXT_SPEED (B9600)
  748. #define VARITEXT_CFLAG (CS7|CREAD|CLOCAL|PARENB|PARODD)
  749. #define VARITEXT_IFLAG (IGNPAR|IGNBRK|INPCK) /*|ISTRIP)*/
  750. #define VARITEXT_OFLAG 0
  751. #define VARITEXT_LFLAG 0
  752. #define VARITEXT_SAMPLES 32
  753. #define VARITEXT_KEEP 20
  754. static struct parse_clockinfo
  755. {
  756. u_long cl_flags; /* operation flags (PPS interpretation, trust handling) */
  757. void (*cl_poll) (struct parseunit *); /* active poll routine */
  758. int (*cl_init) (struct parseunit *); /* active poll init routine */
  759. void (*cl_event) (struct parseunit *, int); /* special event handling (e.g. reset clock) */
  760. void (*cl_end) (struct parseunit *); /* active poll end routine */
  761. void (*cl_message) (struct parseunit *, parsetime_t *); /* process a lower layer message */
  762. void *cl_data; /* local data area for "poll" mechanism */
  763. double cl_rootdelay; /* rootdelay */
  764. double cl_basedelay; /* current offset by which the RS232
  765. time code is delayed from the actual time */
  766. const char *cl_id; /* ID code */
  767. const char *cl_description; /* device name */
  768. const char *cl_format; /* fixed format */
  769. u_char cl_type; /* clock type (ntp control) */
  770. u_long cl_maxunsync; /* time to trust oscillator after losing synch */
  771. u_long cl_speed; /* terminal input & output baudrate */
  772. u_long cl_cflag; /* terminal control flags */
  773. u_long cl_iflag; /* terminal input flags */
  774. u_long cl_oflag; /* terminal output flags */
  775. u_long cl_lflag; /* terminal local flags */
  776. u_long cl_samples; /* samples for median filter */
  777. u_long cl_keep; /* samples for median filter to keep */
  778. } parse_clockinfo[] =
  779. {
  780. { /* mode 0 */
  781. MBG_FLAGS,
  782. NO_POLL,
  783. NO_INIT,
  784. NO_EVENT,
  785. NO_END,
  786. NO_MESSAGE,
  787. NO_LCLDATA,
  788. DCFPZF535_ROOTDELAY,
  789. DCFPZF535_BASEDELAY,
  790. DCF_P_ID,
  791. DCFPZF535_DESCRIPTION,
  792. DCFPZF535_FORMAT,
  793. DCF_TYPE,
  794. DCFPZF535_MAXUNSYNC,
  795. DCFPZF535_SPEED,
  796. DCFPZF535_CFLAG,
  797. DCFPZF535_IFLAG,
  798. DCFPZF535_OFLAG,
  799. DCFPZF535_LFLAG,
  800. DCFPZF535_SAMPLES,
  801. DCFPZF535_KEEP
  802. },
  803. { /* mode 1 */
  804. MBG_FLAGS,
  805. NO_POLL,
  806. NO_INIT,
  807. NO_EVENT,
  808. NO_END,
  809. NO_MESSAGE,
  810. NO_LCLDATA,
  811. DCFPZF535OCXO_ROOTDELAY,
  812. DCFPZF535OCXO_BASEDELAY,
  813. DCF_P_ID,
  814. DCFPZF535OCXO_DESCRIPTION,
  815. DCFPZF535OCXO_FORMAT,
  816. DCF_TYPE,
  817. DCFPZF535OCXO_MAXUNSYNC,
  818. DCFPZF535OCXO_SPEED,
  819. DCFPZF535OCXO_CFLAG,
  820. DCFPZF535OCXO_IFLAG,
  821. DCFPZF535OCXO_OFLAG,
  822. DCFPZF535OCXO_LFLAG,
  823. DCFPZF535OCXO_SAMPLES,
  824. DCFPZF535OCXO_KEEP
  825. },
  826. { /* mode 2 */
  827. MBG_FLAGS,
  828. NO_POLL,
  829. NO_INIT,
  830. NO_EVENT,
  831. NO_END,
  832. NO_MESSAGE,
  833. NO_LCLDATA,
  834. DCFUA31_ROOTDELAY,
  835. DCFUA31_BASEDELAY,
  836. DCF_A_ID,
  837. DCFUA31_DESCRIPTION,
  838. DCFUA31_FORMAT,
  839. DCF_TYPE,
  840. DCFUA31_MAXUNSYNC,
  841. DCFUA31_SPEED,
  842. DCFUA31_CFLAG,
  843. DCFUA31_IFLAG,
  844. DCFUA31_OFLAG,
  845. DCFUA31_LFLAG,
  846. DCFUA31_SAMPLES,
  847. DCFUA31_KEEP
  848. },
  849. { /* mode 3 */
  850. MBG_FLAGS,
  851. NO_POLL,
  852. NO_INIT,
  853. NO_EVENT,
  854. NO_END,
  855. NO_MESSAGE,
  856. NO_LCLDATA,
  857. DCF7000_ROOTDELAY,
  858. DCF7000_BASEDELAY,
  859. DCF_A_ID,
  860. DCF7000_DESCRIPTION,
  861. DCF7000_FORMAT,
  862. DCF_TYPE,
  863. DCF7000_MAXUNSYNC,
  864. DCF7000_SPEED,
  865. DCF7000_CFLAG,
  866. DCF7000_IFLAG,
  867. DCF7000_OFLAG,
  868. DCF7000_LFLAG,
  869. DCF7000_SAMPLES,
  870. DCF7000_KEEP
  871. },
  872. { /* mode 4 */
  873. NO_CL_FLAGS,
  874. WSDCF_POLL,
  875. WSDCF_INIT,
  876. NO_EVENT,
  877. WSDCF_END,
  878. NO_MESSAGE,
  879. WSDCF_DATA,
  880. WSDCF_ROOTDELAY,
  881. WSDCF_BASEDELAY,
  882. DCF_A_ID,
  883. WSDCF_DESCRIPTION,
  884. WSDCF_FORMAT,
  885. DCF_TYPE,
  886. WSDCF_MAXUNSYNC,
  887. WSDCF_SPEED,
  888. WSDCF_CFLAG,
  889. WSDCF_IFLAG,
  890. WSDCF_OFLAG,
  891. WSDCF_LFLAG,
  892. WSDCF_SAMPLES,
  893. WSDCF_KEEP
  894. },
  895. { /* mode 5 */
  896. RAWDCF_FLAGS,
  897. NO_POLL,
  898. RAWDCF_INIT,
  899. NO_EVENT,
  900. NO_END,
  901. NO_MESSAGE,
  902. NO_LCLDATA,
  903. RAWDCF_ROOTDELAY,
  904. CONRAD_BASEDELAY,
  905. DCF_A_ID,
  906. CONRAD_DESCRIPTION,
  907. RAWDCF_FORMAT,
  908. DCF_TYPE,
  909. RAWDCF_MAXUNSYNC,
  910. RAWDCF_SPEED,
  911. RAWDCF_CFLAG,
  912. RAWDCF_IFLAG,
  913. RAWDCF_OFLAG,
  914. RAWDCF_LFLAG,
  915. RAWDCF_SAMPLES,
  916. RAWDCF_KEEP
  917. },
  918. { /* mode 6 */
  919. RAWDCF_FLAGS,
  920. NO_POLL,
  921. RAWDCF_INIT,
  922. NO_EVENT,
  923. NO_END,
  924. NO_MESSAGE,
  925. NO_LCLDATA,
  926. RAWDCF_ROOTDELAY,
  927. TIMEBRICK_BASEDELAY,
  928. DCF_A_ID,
  929. TIMEBRICK_DESCRIPTION,
  930. RAWDCF_FORMAT,
  931. DCF_TYPE,
  932. RAWDCF_MAXUNSYNC,
  933. RAWDCF_SPEED,
  934. RAWDCF_CFLAG,
  935. RAWDCF_IFLAG,
  936. RAWDCF_OFLAG,
  937. RAWDCF_LFLAG,
  938. RAWDCF_SAMPLES,
  939. RAWDCF_KEEP
  940. },
  941. { /* mode 7 */
  942. MBG_FLAGS,
  943. GPS16X_POLL,
  944. GPS16X_INIT,
  945. NO_EVENT,
  946. GPS16X_END,
  947. GPS16X_MESSAGE,
  948. GPS16X_DATA,
  949. GPS16X_ROOTDELAY,
  950. GPS16X_BASEDELAY,
  951. GPS16X_ID,
  952. GPS16X_DESCRIPTION,
  953. GPS16X_FORMAT,
  954. GPS_TYPE,
  955. GPS16X_MAXUNSYNC,
  956. GPS16X_SPEED,
  957. GPS16X_CFLAG,
  958. GPS16X_IFLAG,
  959. GPS16X_OFLAG,
  960. GPS16X_LFLAG,
  961. GPS16X_SAMPLES,
  962. GPS16X_KEEP
  963. },
  964. { /* mode 8 */
  965. RAWDCF_FLAGS,
  966. NO_POLL,
  967. NO_INIT,
  968. NO_EVENT,
  969. NO_END,
  970. NO_MESSAGE,
  971. NO_LCLDATA,
  972. RAWDCF_ROOTDELAY,
  973. IGELCLOCK_BASEDELAY,
  974. DCF_A_ID,
  975. IGELCLOCK_DESCRIPTION,
  976. RAWDCF_FORMAT,
  977. DCF_TYPE,
  978. RAWDCF_MAXUNSYNC,
  979. IGELCLOCK_SPEED,
  980. IGELCLOCK_CFLAG,
  981. RAWDCF_IFLAG,
  982. RAWDCF_OFLAG,
  983. RAWDCF_LFLAG,
  984. RAWDCF_SAMPLES,
  985. RAWDCF_KEEP
  986. },
  987. { /* mode 9 */
  988. TRIMBLETAIP_FLAGS,
  989. #if TRIM_POLLRATE /* DHD940515: Allow user config */
  990. NO_POLL,
  991. #else
  992. TRIMBLETAIP_POLL,
  993. #endif
  994. TRIMBLETAIP_INIT,
  995. TRIMBLETAIP_EVENT,
  996. TRIMBLETAIP_END,
  997. NO_MESSAGE,
  998. TRIMBLETAIP_DATA,
  999. TRIMBLETAIP_ROOTDELAY,
  1000. TRIMBLETAIP_BASEDELAY,
  1001. TRIMBLETAIP_ID,
  1002. TRIMBLETAIP_DESCRIPTION,
  1003. TRIMBLETAIP_FORMAT,
  1004. GPS_TYPE,
  1005. TRIMBLETAIP_MAXUNSYNC,
  1006. TRIMBLETAIP_SPEED,
  1007. TRIMBLETAIP_CFLAG,
  1008. TRIMBLETAIP_IFLAG,
  1009. TRIMBLETAIP_OFLAG,
  1010. TRIMBLETAIP_LFLAG,
  1011. TRIMBLETAIP_SAMPLES,
  1012. TRIMBLETAIP_KEEP
  1013. },
  1014. { /* mode 10 */
  1015. TRIMBLETSIP_FLAGS,
  1016. #if TRIM_POLLRATE /* DHD940515: Allow user config */
  1017. NO_POLL,
  1018. #else
  1019. TRIMBLETSIP_POLL,
  1020. #endif
  1021. TRIMBLETSIP_INIT,
  1022. TRIMBLETSIP_EVENT,
  1023. TRIMBLETSIP_END,
  1024. TRIMBLETSIP_MESSAGE,
  1025. TRIMBLETSIP_DATA,
  1026. TRIMBLETSIP_ROOTDELAY,
  1027. TRIMBLETSIP_BASEDELAY,
  1028. TRIMBLETSIP_ID,
  1029. TRIMBLETSIP_DESCRIPTION,
  1030. TRIMBLETSIP_FORMAT,
  1031. GPS_TYPE,
  1032. TRIMBLETSIP_MAXUNSYNC,
  1033. TRIMBLETSIP_SPEED,
  1034. TRIMBLETSIP_CFLAG,
  1035. TRIMBLETSIP_IFLAG,
  1036. TRIMBLETSIP_OFLAG,
  1037. TRIMBLETSIP_LFLAG,
  1038. TRIMBLETSIP_SAMPLES,
  1039. TRIMBLETSIP_KEEP
  1040. },
  1041. { /* mode 11 */
  1042. NO_CL_FLAGS,
  1043. RCC8000_POLL,
  1044. RCC8000_INIT,
  1045. NO_EVENT,
  1046. RCC8000_END,
  1047. NO_MESSAGE,
  1048. RCC8000_DATA,
  1049. RCC8000_ROOTDELAY,
  1050. RCC8000_BASEDELAY,
  1051. RCC8000_ID,
  1052. RCC8000_DESCRIPTION,
  1053. RCC8000_FORMAT,
  1054. DCF_TYPE,
  1055. RCC8000_MAXUNSYNC,
  1056. RCC8000_SPEED,
  1057. RCC8000_CFLAG,
  1058. RCC8000_IFLAG,
  1059. RCC8000_OFLAG,
  1060. RCC8000_LFLAG,
  1061. RCC8000_SAMPLES,
  1062. RCC8000_KEEP
  1063. },
  1064. { /* mode 12 */
  1065. HOPF6021_FLAGS,
  1066. NO_POLL,
  1067. NO_INIT,
  1068. NO_EVENT,
  1069. NO_END,
  1070. NO_MESSAGE,
  1071. NO_LCLDATA,
  1072. HOPF6021_ROOTDELAY,
  1073. HOPF6021_BASEDELAY,
  1074. DCF_ID,
  1075. HOPF6021_DESCRIPTION,
  1076. HOPF6021_FORMAT,
  1077. DCF_TYPE,
  1078. HOPF6021_MAXUNSYNC,
  1079. HOPF6021_SPEED,
  1080. HOPF6021_CFLAG,
  1081. HOPF6021_IFLAG,
  1082. HOPF6021_OFLAG,
  1083. HOPF6021_LFLAG,
  1084. HOPF6021_SAMPLES,
  1085. HOPF6021_KEEP
  1086. },
  1087. { /* mode 13 */
  1088. COMPUTIME_FLAGS,
  1089. NO_POLL,
  1090. NO_INIT,
  1091. NO_EVENT,
  1092. NO_END,
  1093. NO_MESSAGE,
  1094. NO_LCLDATA,
  1095. COMPUTIME_ROOTDELAY,
  1096. COMPUTIME_BASEDELAY,
  1097. COMPUTIME_ID,
  1098. COMPUTIME_DESCRIPTION,
  1099. COMPUTIME_FORMAT,
  1100. COMPUTIME_TYPE,
  1101. COMPUTIME_MAXUNSYNC,
  1102. COMPUTIME_SPEED,
  1103. COMPUTIME_CFLAG,
  1104. COMPUTIME_IFLAG,
  1105. COMPUTIME_OFLAG,
  1106. COMPUTIME_LFLAG,
  1107. COMPUTIME_SAMPLES,
  1108. COMPUTIME_KEEP
  1109. },
  1110. { /* mode 14 */
  1111. RAWDCF_FLAGS,
  1112. NO_POLL,
  1113. RAWDCFDTRSET_INIT,
  1114. NO_EVENT,
  1115. NO_END,
  1116. NO_MESSAGE,
  1117. NO_LCLDATA,
  1118. RAWDCF_ROOTDELAY,
  1119. RAWDCF_BASEDELAY,
  1120. DCF_A_ID,
  1121. RAWDCFDTRSET_DESCRIPTION,
  1122. RAWDCF_FORMAT,
  1123. DCF_TYPE,
  1124. RAWDCF_MAXUNSYNC,
  1125. RAWDCF_SPEED,
  1126. RAWDCF_CFLAG,
  1127. RAWDCF_IFLAG,
  1128. RAWDCF_OFLAG,
  1129. RAWDCF_LFLAG,
  1130. RAWDCF_SAMPLES,
  1131. RAWDCF_KEEP
  1132. },
  1133. { /* mode 15 */
  1134. 0, /* operation flags (io modes) */
  1135. NO_POLL, /* active poll routine */
  1136. NO_INIT, /* active poll init routine */
  1137. NO_EVENT, /* special event handling (e.g. reset clock) */
  1138. NO_END, /* active poll end routine */
  1139. NO_MESSAGE, /* process a lower layer message */
  1140. NO_LCLDATA, /* local data area for "poll" mechanism */
  1141. 0, /* rootdelay */
  1142. 11.0 /* bits */ / 9600, /* current offset by which the RS232
  1143. time code is delayed from the actual time */
  1144. DCF_ID, /* ID code */
  1145. "WHARTON 400A Series clock", /* device name */
  1146. "WHARTON 400A Series clock Output Format 1", /* fixed format */
  1147. /* Must match a format-name in a libparse/clk_xxx.c file */
  1148. DCF_TYPE, /* clock type (ntp control) */
  1149. (1*60*60), /* time to trust oscillator after losing synch */
  1150. B9600, /* terminal input & output baudrate */
  1151. (CS8|CREAD|PARENB|CLOCAL|HUPCL),/* terminal control flags */
  1152. 0, /* terminal input flags */
  1153. 0, /* terminal output flags */
  1154. 0, /* terminal local flags */
  1155. 5, /* samples for median filter */
  1156. 3, /* samples for median filter to keep */
  1157. },
  1158. { /* mode 16 - RAWDCF RTS set, DTR clr */
  1159. RAWDCF_FLAGS,
  1160. NO_POLL,
  1161. RAWDCFDTRCLRRTSSET_INIT,
  1162. NO_EVENT,
  1163. NO_END,
  1164. NO_MESSAGE,
  1165. NO_LCLDATA,
  1166. RAWDCF_ROOTDELAY,
  1167. RAWDCF_BASEDELAY,
  1168. DCF_A_ID,
  1169. RAWDCFDTRCLRRTSSET_DESCRIPTION,
  1170. RAWDCF_FORMAT,
  1171. DCF_TYPE,
  1172. RAWDCF_MAXUNSYNC,
  1173. RAWDCF_SPEED,
  1174. RAWDCF_CFLAG,
  1175. RAWDCF_IFLAG,
  1176. RAWDCF_OFLAG,
  1177. RAWDCF_LFLAG,
  1178. RAWDCF_SAMPLES,
  1179. RAWDCF_KEEP
  1180. },
  1181. { /* mode 17 */
  1182. VARITEXT_FLAGS,
  1183. NO_POLL,
  1184. NO_INIT,
  1185. NO_EVENT,
  1186. NO_END,
  1187. NO_MESSAGE,
  1188. NO_LCLDATA,
  1189. VARITEXT_ROOTDELAY,
  1190. VARITEXT_BASEDELAY,
  1191. VARITEXT_ID,
  1192. VARITEXT_DESCRIPTION,
  1193. VARITEXT_FORMAT,
  1194. VARITEXT_TYPE,
  1195. VARITEXT_MAXUNSYNC,
  1196. VARITEXT_SPEED,
  1197. VARITEXT_CFLAG,
  1198. VARITEXT_IFLAG,
  1199. VARITEXT_OFLAG,
  1200. VARITEXT_LFLAG,
  1201. VARITEXT_SAMPLES,
  1202. VARITEXT_KEEP
  1203. },
  1204. { /* mode 18 */
  1205. MBG_FLAGS,
  1206. NO_POLL,
  1207. NO_INIT,
  1208. NO_EVENT,
  1209. GPS16X_END,
  1210. GPS16X_MESSAGE,
  1211. GPS16X_DATA,
  1212. GPS16X_ROOTDELAY,
  1213. GPS16X_BASEDELAY,
  1214. GPS16X_ID,
  1215. GPS16X_DESCRIPTION,
  1216. GPS16X_FORMAT,
  1217. GPS_TYPE,
  1218. GPS16X_MAXUNSYNC,
  1219. GPS16X_SPEED,
  1220. GPS16X_CFLAG,
  1221. GPS16X_IFLAG,
  1222. GPS16X_OFLAG,
  1223. GPS16X_LFLAG,
  1224. GPS16X_SAMPLES,
  1225. GPS16X_KEEP
  1226. },
  1227. { /* mode 19 */
  1228. RAWDCF_FLAGS,
  1229. NO_POLL,
  1230. RAWDCF_INIT,
  1231. NO_EVENT,
  1232. NO_END,
  1233. NO_MESSAGE,
  1234. NO_LCLDATA,
  1235. RAWDCF_ROOTDELAY,
  1236. GUDE_EMC_USB_V20_BASEDELAY,
  1237. DCF_A_ID,
  1238. GUDE_EMC_USB_V20_DESCRIPTION,
  1239. RAWDCF_FORMAT,
  1240. DCF_TYPE,
  1241. RAWDCF_MAXUNSYNC,
  1242. GUDE_EMC_USB_V20_SPEED,
  1243. RAWDCF_CFLAG,
  1244. RAWDCF_IFLAG,
  1245. RAWDCF_OFLAG,
  1246. RAWDCF_LFLAG,
  1247. RAWDCF_SAMPLES,
  1248. RAWDCF_KEEP
  1249. },
  1250. { /* mode 20, like mode 14 but driven by 75 baud */
  1251. RAWDCF_FLAGS,
  1252. NO_POLL,
  1253. RAWDCFDTRSET_INIT,
  1254. NO_EVENT,
  1255. NO_END,
  1256. NO_MESSAGE,
  1257. NO_LCLDATA,
  1258. RAWDCF_ROOTDELAY,
  1259. RAWDCF_BASEDELAY,
  1260. DCF_A_ID,
  1261. RAWDCFDTRSET75_DESCRIPTION,
  1262. RAWDCF_FORMAT,
  1263. DCF_TYPE,
  1264. RAWDCF_MAXUNSYNC,
  1265. B75,
  1266. RAWDCF_CFLAG,
  1267. RAWDCF_IFLAG,
  1268. RAWDCF_OFLAG,
  1269. RAWDCF_LFLAG,
  1270. RAWDCF_SAMPLES,
  1271. RAWDCF_KEEP
  1272. },
  1273. { /* mode 21, like mode 16 but driven by 75 baud
  1274. - RAWDCF RTS set, DTR clr */
  1275. RAWDCF_FLAGS,
  1276. NO_POLL,
  1277. RAWDCFDTRCLRRTSSET_INIT,
  1278. NO_EVENT,
  1279. NO_END,
  1280. NO_MESSAGE,
  1281. NO_LCLDATA,
  1282. RAWDCF_ROOTDELAY,
  1283. RAWDCF_BASEDELAY,
  1284. DCF_A_ID,
  1285. RAWDCFDTRCLRRTSSET75_DESCRIPTION,
  1286. RAWDCF_FORMAT,
  1287. DCF_TYPE,
  1288. RAWDCF_MAXUNSYNC,
  1289. B75,
  1290. RAWDCF_CFLAG,
  1291. RAWDCF_IFLAG,
  1292. RAWDCF_OFLAG,
  1293. RAWDCF_LFLAG,
  1294. RAWDCF_SAMPLES,
  1295. RAWDCF_KEEP
  1296. },
  1297. { /* mode 22 - like 2 with POWERUP trust */
  1298. MBG_FLAGS | PARSE_F_POWERUPTRUST,
  1299. NO_POLL,
  1300. NO_INIT,
  1301. NO_EVENT,
  1302. NO_END,
  1303. NO_MESSAGE,
  1304. NO_LCLDATA,
  1305. DCFUA31_ROOTDELAY,
  1306. DCFUA31_BASEDELAY,
  1307. DCF_A_ID,
  1308. DCFUA31_DESCRIPTION,
  1309. DCFUA31_FORMAT,
  1310. DCF_TYPE,
  1311. DCFUA31_MAXUNSYNC,
  1312. DCFUA31_SPEED,
  1313. DCFUA31_CFLAG,
  1314. DCFUA31_IFLAG,
  1315. DCFUA31_OFLAG,
  1316. DCFUA31_LFLAG,
  1317. DCFUA31_SAMPLES,
  1318. DCFUA31_KEEP
  1319. },
  1320. { /* mode 23 - like 7 with POWERUP trust */
  1321. MBG_FLAGS | PARSE_F_POWERUPTRUST,
  1322. GPS16X_POLL,
  1323. GPS16X_INIT,
  1324. NO_EVENT,
  1325. GPS16X_END,
  1326. GPS16X_MESSAGE,
  1327. GPS16X_DATA,
  1328. GPS16X_ROOTDELAY,
  1329. GPS16X_BASEDELAY,
  1330. GPS16X_ID,
  1331. GPS16X_DESCRIPTION,
  1332. GPS16X_FORMAT,
  1333. GPS_TYPE,
  1334. GPS16X_MAXUNSYNC,
  1335. GPS16X_SPEED,
  1336. GPS16X_CFLAG,
  1337. GPS16X_IFLAG,
  1338. GPS16X_OFLAG,
  1339. GPS16X_LFLAG,
  1340. GPS16X_SAMPLES,
  1341. GPS16X_KEEP
  1342. },
  1343. };
  1344. static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
  1345. #define CLK_REALTYPE(x) ((int)(((x)->ttl) & 0x7F))
  1346. #define CLK_TYPE(x) ((CLK_REALTYPE(x) >= ncltypes) ? ~0 : CLK_REALTYPE(x))
  1347. #define CLK_UNIT(x) ((int)REFCLOCKUNIT(&(x)->srcadr))
  1348. #define CLK_PPS(x) (((x)->ttl) & 0x80)
  1349. /*
  1350. * Other constant stuff
  1351. */
  1352. #define PARSEHSREFID 0x7f7f08ff /* 127.127.8.255 refid for hi strata */
  1353. #define PARSESTATISTICS (60*60) /* output state statistics every hour */
  1354. static int notice = 0;
  1355. #define PARSE_STATETIME(parse, i) ((parse->generic->currentstatus == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
  1356. static void parse_event (struct parseunit *, int);
  1357. static void parse_process (struct parseunit *, parsetime_t *);
  1358. static void clear_err (struct parseunit *, u_long);
  1359. static int list_err (struct parseunit *, u_long);
  1360. static char * l_mktime (u_long);
  1361. /**===========================================================================
  1362. ** implementation error message regression module
  1363. **/
  1364. static void
  1365. clear_err(
  1366. struct parseunit *parse,
  1367. u_long lstate
  1368. )
  1369. {
  1370. if (lstate == ERR_ALL)
  1371. {
  1372. int i;
  1373. for (i = 0; i < ERR_CNT; i++)
  1374. {
  1375. parse->errors[i].err_stage = err_tbl[i];
  1376. parse->errors[i].err_cnt = 0;
  1377. parse->errors[i].err_last = 0;
  1378. parse->errors[i].err_started = 0;
  1379. parse->errors[i].err_suppressed = 0;
  1380. }
  1381. }
  1382. else
  1383. {
  1384. parse->errors[lstate].err_stage = err_tbl[lstate];
  1385. parse->errors[lstate].err_cnt = 0;
  1386. parse->errors[lstate].err_last = 0;
  1387. parse->errors[lstate].err_started = 0;
  1388. parse->errors[lstate].err_suppressed = 0;
  1389. }
  1390. }
  1391. static int
  1392. list_err(
  1393. struct parseunit *parse,
  1394. u_long lstate
  1395. )
  1396. {
  1397. int do_it;
  1398. struct errorinfo *err = &parse->errors[lstate];
  1399. if (err->err_started == 0)
  1400. {
  1401. err->err_started = current_time;
  1402. }
  1403. do_it = (current_time - err->err_last) >= err->err_stage->err_delay;
  1404. if (do_it)
  1405. err->err_cnt++;
  1406. if (err->err_stage->err_count &&
  1407. (err->err_cnt >= err->err_stage->err_count))
  1408. {
  1409. err->err_stage++;
  1410. err->err_cnt = 0;
  1411. }
  1412. if (!err->err_cnt && do_it)
  1413. msyslog(LOG_INFO, "PARSE receiver #%d: interval for following error message class is at least %s",
  1414. CLK_UNIT(parse->peer), l_mktime(err->err_stage->err_delay));
  1415. if (!do_it)
  1416. err->err_suppressed++;
  1417. else
  1418. err->err_last = current_time;
  1419. if (do_it && err->err_suppressed)
  1420. {
  1421. msyslog(LOG_INFO, "PARSE receiver #%d: %ld message%s suppressed, error condition class persists for %s",
  1422. CLK_UNIT(parse->peer), err->err_suppressed, (err->err_suppressed == 1) ? " was" : "s where",
  1423. l_mktime(current_time - err->err_started));
  1424. err->err_suppressed = 0;
  1425. }
  1426. return do_it;
  1427. }
  1428. /*--------------------------------------------------
  1429. * mkreadable - make a printable ascii string (without
  1430. * embedded quotes so that the ntpq protocol isn't
  1431. * fooled
  1432. */
  1433. #ifndef isprint
  1434. #define isprint(_X_) (((_X_) > 0x1F) && ((_X_) < 0x7F))
  1435. #endif
  1436. static char *
  1437. mkreadable(
  1438. char *buffer,
  1439. long blen,
  1440. const char *src,
  1441. u_long srclen,
  1442. int hex
  1443. )
  1444. {
  1445. char *b = buffer;
  1446. char *endb = NULL;
  1447. if (blen < 4)
  1448. return NULL; /* don't bother with mini buffers */
  1449. endb = buffer + blen - 4;
  1450. blen--; /* account for '\0' */
  1451. while (blen && srclen--)
  1452. {
  1453. if (!hex && /* no binary only */
  1454. (*src != '\\') && /* no plain \ */
  1455. (*src != '"') && /* no " */
  1456. isprint((int)*src)) /* only printables */
  1457. { /* they are easy... */
  1458. *buffer++ = *src++;
  1459. blen--;
  1460. }
  1461. else
  1462. {
  1463. if (blen < 4)
  1464. {
  1465. while (blen--)
  1466. {
  1467. *buffer++ = '.';
  1468. }
  1469. *buffer = '\0';
  1470. return b;
  1471. }
  1472. else
  1473. {
  1474. if (*src == '\\')
  1475. {
  1476. strcpy(buffer,"\\\\");
  1477. buffer += 2;
  1478. blen -= 2;
  1479. src++;
  1480. }
  1481. else
  1482. {
  1483. snprintf(buffer, blen, "\\x%02x", *src++);
  1484. blen -= 4;
  1485. buffer += 4;
  1486. }
  1487. }
  1488. }
  1489. if (srclen && !blen && endb) /* overflow - set last chars to ... */
  1490. strcpy(endb, "...");
  1491. }
  1492. *buffer = '\0';
  1493. return b;
  1494. }
  1495. /*--------------------------------------------------
  1496. * mkascii - make a printable ascii string
  1497. * assumes (unless defined better) 7-bit ASCII
  1498. */
  1499. static char *
  1500. mkascii(
  1501. char *buffer,
  1502. long blen,
  1503. const char *src,
  1504. u_long srclen
  1505. )
  1506. {
  1507. return mkreadable(buffer, blen, src, srclen, 0);
  1508. }
  1509. /**===========================================================================
  1510. ** implementation of i/o handling methods
  1511. ** (all STREAM, partial STREAM, user level)
  1512. **/
  1513. /*
  1514. * define possible io handling methods
  1515. */
  1516. #ifdef STREAM
  1517. static int ppsclock_init (struct parseunit *);
  1518. static int stream_init (struct parseunit *);
  1519. static void stream_end (struct parseunit *);
  1520. static int stream_enable (struct parseunit *);
  1521. static int stream_disable (struct parseunit *);
  1522. static int stream_setcs (struct parseunit *, parsectl_t *);
  1523. static int stream_getfmt (struct parseunit *, parsectl_t *);
  1524. static int stream_setfmt (struct parseunit *, parsectl_t *);
  1525. static int stream_timecode (struct parseunit *, parsectl_t *);
  1526. static void stream_receive (struct recvbuf *);
  1527. #endif
  1528. static int local_init (struct parseunit *);
  1529. static void local_end (struct parseunit *);
  1530. static int local_nop (struct parseunit *);
  1531. static int local_setcs (struct parseunit *, parsectl_t *);
  1532. static int local_getfmt (struct parseunit *, parsectl_t *);
  1533. static int local_setfmt (struct parseunit *, parsectl_t *);
  1534. static int local_timecode (struct parseunit *, parsectl_t *);
  1535. static void local_receive (struct recvbuf *);
  1536. static int local_input (struct recvbuf *);
  1537. static bind_t io_bindings[] =
  1538. {
  1539. #ifdef STREAM
  1540. {
  1541. "parse STREAM",
  1542. stream_init,
  1543. stream_end,
  1544. stream_setcs,
  1545. stream_disable,
  1546. stream_enable,
  1547. stream_getfmt,
  1548. stream_setfmt,
  1549. stream_timecode,
  1550. stream_receive,
  1551. 0,
  1552. },
  1553. {
  1554. "ppsclock STREAM",
  1555. ppsclock_init,
  1556. local_end,
  1557. local_setcs,
  1558. local_nop,
  1559. local_nop,
  1560. local_getfmt,
  1561. local_setfmt,
  1562. local_timecode,
  1563. local_receive,
  1564. local_input,
  1565. },
  1566. #endif
  1567. {
  1568. "normal",
  1569. local_init,
  1570. local_end,
  1571. local_setcs,
  1572. local_nop,
  1573. local_nop,
  1574. local_getfmt,
  1575. local_setfmt,
  1576. local_timecode,
  1577. local_receive,
  1578. local_input,
  1579. },
  1580. {
  1581. (char *)0,
  1582. }
  1583. };
  1584. #ifdef STREAM
  1585. #define fix_ts(_X_) \
  1586. if ((&(_X_))->tv.tv_usec >= 1000000) \
  1587. { \
  1588. (&(_X_))->tv.tv_usec -= 1000000; \
  1589. (&(_X_))->tv.tv_sec += 1; \
  1590. }
  1591. #define cvt_ts(_X_, _Y_) \
  1592. { \
  1593. l_fp ts; \
  1594. fix_ts((_X_)); \
  1595. if (!buftvtots((const char *)&(&(_X_))->tv, &ts)) \
  1596. { \
  1597. ERR(ERR_BADDATA) \
  1598. msyslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%ld.%06ld) ", (_Y_), (long)(&(_X_))->tv.tv_sec, (long)(&(_X_))->tv.tv_usec);\
  1599. return; \
  1600. } \
  1601. else \
  1602. { \
  1603. (&(_X_))->fp = ts; \
  1604. } \
  1605. }
  1606. /*--------------------------------------------------
  1607. * ppsclock STREAM init
  1608. */
  1609. static int
  1610. ppsclock_init(
  1611. struct parseunit *parse
  1612. )
  1613. {
  1614. static char m1[] = "ppsclocd";
  1615. static char m2[] = "ppsclock";
  1616. /*
  1617. * now push the parse streams module
  1618. * it will ensure exclusive access to the device
  1619. */
  1620. if (ioctl(parse->ppsfd, I_PUSH, (caddr_t)m1) == -1 &&
  1621. ioctl(parse->ppsfd, I_PUSH, (caddr_t)m2) == -1)
  1622. {
  1623. if (errno != EINVAL)
  1624. {
  1625. msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
  1626. CLK_UNIT(parse->peer));
  1627. }
  1628. return 0;
  1629. }
  1630. if (!local_init(parse))
  1631. {
  1632. (void)ioctl(parse->ppsfd, I_POP, (caddr_t)0);
  1633. return 0;
  1634. }
  1635. parse->flags |= PARSE_PPSCLOCK;
  1636. return 1;
  1637. }
  1638. /*--------------------------------------------------
  1639. * parse STREAM init
  1640. */
  1641. static int
  1642. stream_init(
  1643. struct parseunit *parse
  1644. )
  1645. {
  1646. static char m1[] = "parse";
  1647. /*
  1648. * now push the parse streams module
  1649. * to test whether it is there (neat interface 8-( )
  1650. */
  1651. if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
  1652. {
  1653. if (errno != EINVAL) /* accept non-existence */
  1654. {
  1655. msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
  1656. }
  1657. return 0;
  1658. }
  1659. else
  1660. {
  1661. while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
  1662. /* empty loop */;
  1663. /*
  1664. * now push it a second time after we have removed all
  1665. * module garbage
  1666. */
  1667. if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
  1668. {
  1669. msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
  1670. return 0;
  1671. }
  1672. else
  1673. {
  1674. return 1;
  1675. }
  1676. }
  1677. }
  1678. /*--------------------------------------------------
  1679. * parse STREAM end
  1680. */
  1681. static void
  1682. stream_end(
  1683. struct parseunit *parse
  1684. )
  1685. {
  1686. while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
  1687. /* empty loop */;
  1688. }
  1689. /*--------------------------------------------------
  1690. * STREAM setcs
  1691. */
  1692. static int
  1693. stream_setcs(
  1694. struct parseunit *parse,
  1695. parsectl_t *tcl
  1696. )
  1697. {
  1698. struct strioctl strioc;
  1699. strioc.ic_cmd = PARSEIOC_SETCS;
  1700. strioc.ic_timout = 0;
  1701. strioc.ic_dp = (char *)tcl;
  1702. strioc.ic_len = sizeof (*tcl);
  1703. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1704. {
  1705. msyslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CLK_UNIT(parse->peer));
  1706. return 0;
  1707. }
  1708. return 1;
  1709. }
  1710. /*--------------------------------------------------
  1711. * STREAM enable
  1712. */
  1713. static int
  1714. stream_enable(
  1715. struct parseunit *parse
  1716. )
  1717. {
  1718. struct strioctl strioc;
  1719. strioc.ic_cmd = PARSEIOC_ENABLE;
  1720. strioc.ic_timout = 0;
  1721. strioc.ic_dp = (char *)0;
  1722. strioc.ic_len = 0;
  1723. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1724. {
  1725. msyslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CLK_UNIT(parse->peer));
  1726. return 0;
  1727. }
  1728. parse->generic->io.clock_recv = stream_receive; /* ok - parse input in kernel */
  1729. return 1;
  1730. }
  1731. /*--------------------------------------------------
  1732. * STREAM disable
  1733. */
  1734. static int
  1735. stream_disable(
  1736. struct parseunit *parse
  1737. )
  1738. {
  1739. struct strioctl strioc;
  1740. strioc.ic_cmd = PARSEIOC_DISABLE;
  1741. strioc.ic_timout = 0;
  1742. strioc.ic_dp = (char *)0;
  1743. strioc.ic_len = 0;
  1744. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1745. {
  1746. msyslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CLK_UNIT(parse->peer));
  1747. return 0;
  1748. }
  1749. parse->generic->io.clock_recv = local_receive; /* ok - parse input in daemon */
  1750. return 1;
  1751. }
  1752. /*--------------------------------------------------
  1753. * STREAM getfmt
  1754. */
  1755. static int
  1756. stream_getfmt(
  1757. struct parseunit *parse,
  1758. parsectl_t *tcl
  1759. )
  1760. {
  1761. struct strioctl strioc;
  1762. strioc.ic_cmd = PARSEIOC_GETFMT;
  1763. strioc.ic_timout = 0;
  1764. strioc.ic_dp = (char *)tcl;
  1765. strioc.ic_len = sizeof (*tcl);
  1766. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1767. {
  1768. msyslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CLK_UNIT(parse->peer));
  1769. return 0;
  1770. }
  1771. return 1;
  1772. }
  1773. /*--------------------------------------------------
  1774. * STREAM setfmt
  1775. */
  1776. static int
  1777. stream_setfmt(
  1778. struct parseunit *parse,
  1779. parsectl_t *tcl
  1780. )
  1781. {
  1782. struct strioctl strioc;
  1783. strioc.ic_cmd = PARSEIOC_SETFMT;
  1784. strioc.ic_timout = 0;
  1785. strioc.ic_dp = (char *)tcl;
  1786. strioc.ic_len = sizeof (*tcl);
  1787. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1788. {
  1789. msyslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CLK_UNIT(parse->peer));
  1790. return 0;
  1791. }
  1792. return 1;
  1793. }
  1794. /*--------------------------------------------------
  1795. * STREAM timecode
  1796. */
  1797. static int
  1798. stream_timecode(
  1799. struct parseunit *parse,
  1800. parsectl_t *tcl
  1801. )
  1802. {
  1803. struct strioctl strioc;
  1804. strioc.ic_cmd = PARSEIOC_TIMECODE;
  1805. strioc.ic_timout = 0;
  1806. strioc.ic_dp = (char *)tcl;
  1807. strioc.ic_len = sizeof (*tcl);
  1808. if (ioctl(parse->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
  1809. {
  1810. ERR(ERR_INTERNAL)
  1811. msyslog(LOG_ERR, "PARSE receiver #%d: stream_timecode: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CLK_UNIT(parse->peer));
  1812. return 0;
  1813. }
  1814. clear_err(parse, ERR_INTERNAL);
  1815. return 1;
  1816. }
  1817. /*--------------------------------------------------
  1818. * STREAM receive
  1819. */
  1820. static void
  1821. stream_receive(
  1822. struct recvbuf *rbufp
  1823. )
  1824. {
  1825. struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
  1826. parsetime_t parsetime;
  1827. if (!parse->peer)
  1828. return;
  1829. if (rbufp->recv_length != sizeof(parsetime_t))
  1830. {
  1831. ERR(ERR_BADIO)
  1832. msyslog(LOG_ERR,"PARSE receiver #%d: stream_receive: bad size (got %d expected %d)",
  1833. CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
  1834. parse_event(parse, CEVNT_BADREPLY);
  1835. return;
  1836. }
  1837. clear_err(parse, ERR_BADIO);
  1838. memmove((caddr_t)&parsetime,
  1839. (caddr_t)rbufp->recv_buffer,
  1840. sizeof(parsetime_t));
  1841. #ifdef DEBUG
  1842. if (debug > 3)
  1843. {
  1844. printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
  1845. CLK_UNIT(parse->peer),
  1846. (unsigned int)parsetime.parse_status,
  1847. (unsigned int)parsetime.parse_state,
  1848. (unsigned long)parsetime.parse_time.tv.tv_sec,
  1849. (unsigned long)parsetime.parse_time.tv.tv_usec,
  1850. (unsigned long)parsetime.parse_stime.tv.tv_sec,
  1851. (unsigned long)parsetime.parse_stime.tv.tv_usec,
  1852. (unsigned long)parsetime.parse_ptime.tv.tv_sec,
  1853. (unsigned long)parsetime.parse_ptime.tv.tv_usec);
  1854. }
  1855. #endif
  1856. /*
  1857. * switch time stamp world - be sure to normalize small usec field
  1858. * errors.
  1859. */
  1860. cvt_ts(parsetime.parse_stime, "parse_stime");
  1861. if (PARSE_TIMECODE(parsetime.parse_state))
  1862. {
  1863. cvt_ts(parsetime.parse_time, "parse_time");
  1864. }
  1865. if (PARSE_PPS(parsetime.parse_state))
  1866. cvt_ts(parsetime.parse_ptime, "parse_ptime");
  1867. parse_process(parse, &parsetime);
  1868. }
  1869. #endif
  1870. /*--------------------------------------------------
  1871. * local init
  1872. */
  1873. static int
  1874. local_init(
  1875. struct parseunit *parse
  1876. )
  1877. {
  1878. return parse_ioinit(&parse->parseio);
  1879. }
  1880. /*--------------------------------------------------
  1881. * local end
  1882. */
  1883. static void
  1884. local_end(
  1885. struct parseunit *parse
  1886. )
  1887. {
  1888. parse_ioend(&parse->parseio);
  1889. }
  1890. /*--------------------------------------------------
  1891. * local nop
  1892. */
  1893. static int
  1894. local_nop(
  1895. struct parseunit *parse
  1896. )
  1897. {
  1898. return 1;
  1899. }
  1900. /*--------------------------------------------------
  1901. * local setcs
  1902. */
  1903. static int
  1904. local_setcs(
  1905. struct parseunit *parse,
  1906. parsectl_t *tcl
  1907. )
  1908. {
  1909. return parse_setcs(tcl, &parse->parseio);
  1910. }
  1911. /*--------------------------------------------------
  1912. * local getfmt
  1913. */
  1914. static int
  1915. local_getfmt(
  1916. struct parseunit *parse,
  1917. parsectl_t *tcl
  1918. )
  1919. {
  1920. return parse_getfmt(tcl, &parse->parseio);
  1921. }
  1922. /*--------------------------------------------------
  1923. * local setfmt
  1924. */
  1925. static int
  1926. local_setfmt(
  1927. struct parseunit *parse,
  1928. parsectl_t *tcl
  1929. )
  1930. {
  1931. return parse_setfmt(tcl, &parse->parseio);
  1932. }
  1933. /*--------------------------------------------------
  1934. * local timecode
  1935. */
  1936. static int
  1937. local_timecode(
  1938. struct parseunit *parse,
  1939. parsectl_t *tcl
  1940. )
  1941. {
  1942. return parse_timecode(tcl, &parse->parseio);
  1943. }
  1944. /*--------------------------------------------------
  1945. * local input
  1946. */
  1947. static int
  1948. local_input(
  1949. struct recvbuf *rbufp
  1950. )
  1951. {
  1952. struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
  1953. int count;
  1954. unsigned char *s;
  1955. timestamp_t ts;
  1956. if (!parse->peer)
  1957. return 0;
  1958. /*
  1959. * eat all characters, parsing then and feeding complete samples
  1960. */
  1961. count = rbufp->recv_length;
  1962. s = (unsigned char *)rbufp->recv_buffer;
  1963. ts.fp = rbufp->recv_time;
  1964. while (count--)
  1965. {
  1966. if (parse_ioread(&parse->parseio, (unsigned int)(*s++), &ts))
  1967. {
  1968. struct recvbuf *buf;
  1969. /*
  1970. * got something good to eat
  1971. */
  1972. if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state))
  1973. {
  1974. #ifdef HAVE_PPSAPI
  1975. if (parse->flags & PARSE_PPSCLOCK)
  1976. {
  1977. struct timespec pps_timeout;
  1978. pps_info_t pps_info;
  1979. pps_timeout.tv_sec = 0;
  1980. pps_timeout.tv_nsec = 0;
  1981. if (time_pps_fetch(parse->atom.handle, PPS_TSFMT_TSPEC, &pps_info,
  1982. &pps_timeout) == 0)
  1983. {
  1984. if (pps_info.assert_sequence + pps_info.clear_sequence != parse->ppsserial)
  1985. {
  1986. double dtemp;
  1987. struct timespec pts;
  1988. /*
  1989. * add PPS time stamp if available via ppsclock module
  1990. * and not supplied already.
  1991. */
  1992. if (parse->flags & PARSE_CLEAR)
  1993. pts = pps_info.clear_timestamp;
  1994. else
  1995. pts = pps_info.assert_timestamp;
  1996. parse->parseio.parse_dtime.parse_ptime.fp.l_ui = pts.tv_sec + JAN_1970;
  1997. dtemp = pts.tv_nsec / 1e9;
  1998. if (dtemp < 0.) {
  1999. dtemp += 1;
  2000. parse->parseio.parse_dtime.parse_ptime.fp.l_ui--;
  2001. }
  2002. if (dtemp > 1.) {
  2003. dtemp -= 1;
  2004. parse->parseio.parse_dtime.parse_ptime.fp.l_ui++;
  2005. }
  2006. parse->parseio.parse_dtime.parse_ptime.fp.l_uf = dtemp * FRAC;
  2007. parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  2008. #ifdef DEBUG
  2009. if (debug > 3)
  2010. {
  2011. printf(
  2012. "parse: local_receive: fd %d PPSAPI seq %ld - PPS %s\n",
  2013. rbufp->fd,
  2014. (long)pps_info.assert_sequence + (long)pps_info.clear_sequence,
  2015. lfptoa(&parse->parseio.parse_dtime.parse_ptime.fp, 6));
  2016. }
  2017. #endif
  2018. }
  2019. #ifdef DEBUG
  2020. else
  2021. {
  2022. if (debug > 3)
  2023. {
  2024. printf(
  2025. "parse: local_receive: fd %d PPSAPI seq assert %ld, seq clear %ld - NO PPS event\n",
  2026. rbufp->fd,
  2027. (long)pps_info.assert_sequence, (long)pps_info.clear_sequence);
  2028. }
  2029. }
  2030. #endif
  2031. parse->ppsserial = pps_info.assert_sequence + pps_info.clear_sequence;
  2032. }
  2033. #ifdef DEBUG
  2034. else
  2035. {
  2036. if (debug > 3)
  2037. {
  2038. printf(
  2039. "parse: local_receive: fd %d PPSAPI time_pps_fetch errno = %d\n",
  2040. rbufp->fd,
  2041. errno);
  2042. }
  2043. }
  2044. #endif
  2045. }
  2046. #else
  2047. #ifdef TIOCDCDTIMESTAMP
  2048. struct timeval dcd_time;
  2049. if (ioctl(parse->ppsfd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
  2050. {
  2051. l_fp tstmp;
  2052. TVTOTS(&dcd_time, &tstmp);
  2053. tstmp.l_ui += JAN_1970;
  2054. L_SUB(&ts.fp, &tstmp);
  2055. if (ts.fp.l_ui == 0)
  2056. {
  2057. #ifdef DEBUG
  2058. if (debug)
  2059. {
  2060. printf(
  2061. "parse: local_receive: fd %d DCDTIMESTAMP %s\n",
  2062. parse->ppsfd,
  2063. lfptoa(&tstmp, 6));
  2064. printf(" sigio %s\n",
  2065. lfptoa(&ts.fp, 6));
  2066. }
  2067. #endif
  2068. parse->parseio.parse_dtime.parse_ptime.fp = tstmp;
  2069. parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  2070. }
  2071. }
  2072. #else /* TIOCDCDTIMESTAMP */
  2073. #if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
  2074. if (parse->flags & PARSE_PPSCLOCK)
  2075. {
  2076. l_fp tts;
  2077. struct ppsclockev ev;
  2078. #ifdef HAVE_CIOGETEV
  2079. if (ioctl(parse->ppsfd, CIOGETEV, (caddr_t)&ev) == 0)
  2080. #endif
  2081. #ifdef HAVE_TIOCGPPSEV
  2082. if (ioctl(parse->ppsfd, TIOCGPPSEV, (caddr_t)&ev) == 0)
  2083. #endif
  2084. {
  2085. if (ev.serial != parse->ppsserial)
  2086. {
  2087. /*
  2088. * add PPS time stamp if available via ppsclock module
  2089. * and not supplied already.
  2090. */
  2091. if (!buftvtots((const char *)&ev.tv, &tts))
  2092. {
  2093. ERR(ERR_BADDATA)
  2094. msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
  2095. }
  2096. else
  2097. {
  2098. parse->parseio.parse_dtime.parse_ptime.fp = tts;
  2099. parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  2100. }
  2101. }
  2102. parse->ppsserial = ev.serial;
  2103. }
  2104. }
  2105. #endif
  2106. #endif /* TIOCDCDTIMESTAMP */
  2107. #endif /* !HAVE_PPSAPI */
  2108. }
  2109. if (count)
  2110. { /* simulate receive */
  2111. buf = get_free_recv_buffer();
  2112. if (buf != NULL) {
  2113. memmove((caddr_t)buf->recv_buffer,
  2114. (caddr_t)&parse->parseio.parse_dtime,
  2115. sizeof(parsetime_t));
  2116. buf->recv_length = sizeof(parsetime_t);
  2117. buf->recv_time = rbufp->recv_time;
  2118. buf->srcadr = rbufp->srcadr;
  2119. buf->dstadr = rbufp->dstadr;
  2120. buf->receiver = rbufp->receiver;
  2121. buf->fd = rbufp->fd;
  2122. buf->X_from_where = rbufp->X_from_where;
  2123. add_full_recv_buffer(buf);
  2124. }
  2125. parse_iodone(&parse->parseio);
  2126. }
  2127. else
  2128. {
  2129. memmove((caddr_t)rbufp->recv_buffer,
  2130. (caddr_t)&parse->parseio.parse_dtime,
  2131. sizeof(parsetime_t));
  2132. parse_iodone(&parse->parseio);
  2133. rbufp->recv_length = sizeof(parsetime_t);
  2134. return 1; /* got something & in place return */
  2135. }
  2136. }
  2137. }
  2138. return 0; /* nothing to pass up */
  2139. }
  2140. /*--------------------------------------------------
  2141. * local receive
  2142. */
  2143. static void
  2144. local_receive(
  2145. struct recvbuf *rbufp
  2146. )
  2147. {
  2148. struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
  2149. parsetime_t parsetime;
  2150. if (!parse->peer)
  2151. return;
  2152. if (rbufp->recv_length != sizeof(parsetime_t))
  2153. {
  2154. ERR(ERR_BADIO)
  2155. msyslog(LOG_ERR,"PARSE receiver #%d: local_receive: bad size (got %d expected %d)",
  2156. CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
  2157. parse_event(parse, CEVNT_BADREPLY);
  2158. return;
  2159. }
  2160. clear_err(parse, ERR_BADIO);
  2161. memmove((caddr_t)&parsetime,
  2162. (caddr_t)rbufp->recv_buffer,
  2163. sizeof(parsetime_t));
  2164. #ifdef DEBUG
  2165. if (debug > 3)
  2166. {
  2167. printf("PARSE receiver #%d: status %06x, state %08x, time(fp) %lx.%08lx, stime(fp) %lx.%08lx, ptime(fp) %lx.%08lx\n",
  2168. CLK_UNIT(parse->peer),
  2169. (unsigned int)parsetime.parse_status,
  2170. (unsigned int)parsetime.parse_state,
  2171. (unsigned long)parsetime.parse_time.fp.l_ui,
  2172. (unsigned long)parsetime.parse_time.fp.l_uf,
  2173. (unsigned long)parsetime.parse_stime.fp.l_ui,
  2174. (unsigned long)parsetime.parse_stime.fp.l_uf,
  2175. (unsigned long)parsetime.parse_ptime.fp.l_ui,
  2176. (unsigned long)parsetime.parse_ptime.fp.l_uf);
  2177. }
  2178. #endif
  2179. parse_process(parse, &parsetime);
  2180. }
  2181. /*--------------------------------------------------
  2182. * init_iobinding - find and initialize lower layers
  2183. */
  2184. static bind_t *
  2185. init_iobinding(
  2186. struct parseunit *parse
  2187. )
  2188. {
  2189. bind_t *b = io_bindings;
  2190. while (b->bd_description != (char *)0)
  2191. {
  2192. if ((*b->bd_init)(parse))
  2193. {
  2194. return b;
  2195. }
  2196. b++;
  2197. }
  2198. return (bind_t *)0;
  2199. }
  2200. /**===========================================================================
  2201. ** support routines
  2202. **/
  2203. /*--------------------------------------------------
  2204. * convert a flag field to a string
  2205. */
  2206. static char *
  2207. parsestate(
  2208. u_long lstate,
  2209. char *buffer,
  2210. int size
  2211. )
  2212. {
  2213. static struct bits
  2214. {
  2215. u_long bit;
  2216. const char *name;
  2217. } flagstrings[] =
  2218. {
  2219. { PARSEB_ANNOUNCE, "DST SWITCH WARNING" },
  2220. { PARSEB_POWERUP, "NOT SYNCHRONIZED" },
  2221. { PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" },
  2222. { PARSEB_DST, "DST" },
  2223. { PARSEB_UTC, "UTC DISPLAY" },
  2224. { PARSEB_LEAPADD, "LEAP ADD WARNING" },
  2225. { PARSEB_LEAPDEL, "LEAP DELETE WARNING" },
  2226. { PARSEB_LEAPSECOND, "LEAP SECOND" },
  2227. { PARSEB_ALTERNATE, "ALTERNATE ANTENNA" },
  2228. { PARSEB_TIMECODE, "TIME CODE" },
  2229. { PARSEB_PPS, "PPS" },
  2230. { PARSEB_POSITION, "POSITION" },
  2231. { 0 }
  2232. };
  2233. static struct sbits
  2234. {
  2235. u_long bit;
  2236. const char *name;
  2237. } sflagstrings[] =
  2238. {
  2239. { PARSEB_S_LEAP, "LEAP INDICATION" },
  2240. { PARSEB_S_PPS, "PPS SIGNAL" },
  2241. { PARSEB_S_ANTENNA, "ANTENNA" },
  2242. { PARSEB_S_POSITION, "POSITION" },
  2243. { 0 }
  2244. };
  2245. int i;
  2246. char *s, *t;
  2247. *buffer = '\0';
  2248. s = t = buffer;
  2249. i = 0;
  2250. while (flagstrings[i].bit)
  2251. {
  2252. if (flagstrings[i].bit & lstate)
  2253. {
  2254. if (s != t)
  2255. strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
  2256. strncat(t, flagstrings[i].name, BUFFER_SIZES(buffer, t, size));
  2257. t += strlen(t);
  2258. }
  2259. i++;
  2260. }
  2261. if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
  2262. {
  2263. if (s != t)
  2264. strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
  2265. t += strlen(t);
  2266. strncpy(t, "(", BUFFER_SIZES(buffer, t, size));
  2267. s = t = t + strlen(t);
  2268. i = 0;
  2269. while (sflagstrings[i].bit)
  2270. {
  2271. if (sflagstrings[i].bit & lstate)
  2272. {
  2273. if (t != s)
  2274. {
  2275. strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
  2276. t += 2;
  2277. }
  2278. strncpy(t, sflagstrings[i].name, BUFFER_SIZES(buffer, t, size));
  2279. t += strlen(t);
  2280. }
  2281. i++;
  2282. }
  2283. strncpy(t, ")", BUFFER_SIZES(buffer, t, size));
  2284. }
  2285. return buffer;
  2286. }
  2287. /*--------------------------------------------------
  2288. * convert a status flag field to a string
  2289. */
  2290. static char *
  2291. parsestatus(
  2292. u_long lstate,
  2293. char *buffer,
  2294. int size
  2295. )
  2296. {
  2297. static struct bits
  2298. {
  2299. u_long bit;
  2300. const char *name;
  2301. } flagstrings[] =
  2302. {
  2303. { CVT_OK, "CONVERSION SUCCESSFUL" },
  2304. { CVT_NONE, "NO CONVERSION" },
  2305. { CVT_FAIL, "CONVERSION FAILED" },
  2306. { CVT_BADFMT, "ILLEGAL FORMAT" },
  2307. { CVT_BADDATE, "DATE ILLEGAL" },
  2308. { CVT_BADTIME, "TIME ILLEGAL" },
  2309. { CVT_ADDITIONAL, "ADDITIONAL DATA" },
  2310. { 0 }
  2311. };
  2312. int i;
  2313. *buffer = '\0';
  2314. i = 0;
  2315. while (flagstrings[i].bit)
  2316. {
  2317. if (flagstrings[i].bit & lstate)
  2318. {
  2319. if (buffer[0])
  2320. strncat(buffer, "; ", size);
  2321. strncat(buffer, flagstrings[i].name, size);
  2322. }
  2323. i++;
  2324. }
  2325. return buffer;
  2326. }
  2327. /*--------------------------------------------------
  2328. * convert a clock status flag field to a string
  2329. */
  2330. static const char *
  2331. clockstatus(
  2332. u_long lstate
  2333. )
  2334. {
  2335. static char buffer[20];
  2336. static struct status
  2337. {
  2338. u_long value;
  2339. const char *name;
  2340. } flagstrings[] =
  2341. {
  2342. { CEVNT_NOMINAL, "NOMINAL" },
  2343. { CEVNT_TIMEOUT, "NO RESPONSE" },
  2344. { CEVNT_BADREPLY,"BAD FORMAT" },
  2345. { CEVNT_FAULT, "FAULT" },
  2346. { CEVNT_PROP, "PROPAGATION DELAY" },
  2347. { CEVNT_BADDATE, "ILLEGAL DATE" },
  2348. { CEVNT_BADTIME, "ILLEGAL TIME" },
  2349. { (unsigned)~0L }
  2350. };
  2351. int i;
  2352. i = 0;
  2353. while (flagstrings[i].value != ~0)
  2354. {
  2355. if (flagstrings[i].value == lstate)
  2356. {
  2357. return flagstrings[i].name;
  2358. }
  2359. i++;
  2360. }
  2361. snprintf(buffer, sizeof(buffer), "unknown #%ld", (u_long)lstate);
  2362. return buffer;
  2363. }
  2364. /*--------------------------------------------------
  2365. * l_mktime - make representation of a relative time
  2366. */
  2367. static char *
  2368. l_mktime(
  2369. u_long delta
  2370. )
  2371. {
  2372. u_long tmp, m, s;
  2373. static char buffer[40];
  2374. char *t;
  2375. buffer[0] = '\0';
  2376. if ((tmp = delta / (60*60*24)) != 0)
  2377. {
  2378. snprintf(buffer, BUFFER_SIZE(buffer, buffer), "%ldd+", (u_long)tmp);
  2379. delta -= tmp * 60*60*24;
  2380. }
  2381. s = delta % 60;
  2382. delta /= 60;
  2383. m = delta % 60;
  2384. delta /= 60;
  2385. t = buffer + strlen(buffer);
  2386. snprintf(t, BUFFER_SIZE(buffer, t), "%02d:%02d:%02d",
  2387. (int)delta, (int)m, (int)s);
  2388. return buffer;
  2389. }
  2390. /*--------------------------------------------------
  2391. * parse_statistics - list summary of clock states
  2392. */
  2393. static void
  2394. parse_statistics(
  2395. struct parseunit *parse
  2396. )
  2397. {
  2398. int i;
  2399. NLOG(NLOG_CLOCKSTATIST) /* conditional if clause for conditional syslog */
  2400. {
  2401. msyslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
  2402. CLK_UNIT(parse->peer),
  2403. l_mktime(current_time - parse->generic->timestarted));
  2404. msyslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
  2405. CLK_UNIT(parse->peer),
  2406. clockstatus(parse->generic->currentstatus));
  2407. for (i = 0; i <= CEVNT_MAX; i++)
  2408. {
  2409. u_long s_time;
  2410. u_long percent, d = current_time - parse->generic->timestarted;
  2411. percent = s_time = PARSE_STATETIME(parse, i);
  2412. while (((u_long)(~0) / 10000) < percent)
  2413. {
  2414. percent /= 10;
  2415. d /= 10;
  2416. }
  2417. if (d)
  2418. percent = (percent * 10000) / d;
  2419. else
  2420. percent = 10000;
  2421. if (s_time)
  2422. msyslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3ld.%02ld%%)",
  2423. CLK_UNIT(parse->peer),
  2424. clockstatus((unsigned int)i),
  2425. l_mktime(s_time),
  2426. percent / 100, percent % 100);
  2427. }
  2428. }
  2429. }
  2430. /*--------------------------------------------------
  2431. * cparse_statistics - wrapper for statistics call
  2432. */
  2433. static void
  2434. cparse_statistics(
  2435. struct parseunit *parse
  2436. )
  2437. {
  2438. if (parse->laststatistic + PARSESTATISTICS < current_time)
  2439. parse_statistics(parse);
  2440. parse->laststatistic = current_time;
  2441. }
  2442. /**===========================================================================
  2443. ** ntp interface routines
  2444. **/
  2445. /*--------------------------------------------------
  2446. * parse_shutdown - shut down a PARSE clock
  2447. */
  2448. static void
  2449. parse_shutdown(
  2450. int unit,
  2451. struct peer *peer
  2452. )
  2453. {
  2454. struct parseunit *parse = (struct parseunit *)0;
  2455. if (peer && peer->procptr)
  2456. parse = (struct parseunit *)peer->procptr->unitptr;
  2457. if (!parse)
  2458. {
  2459. /* nothing to clean up */
  2460. return;
  2461. }
  2462. if (!parse->peer)
  2463. {
  2464. msyslog(LOG_INFO, "PARSE receiver #%d: INTERNAL ERROR - unit already inactive - shutdown ignored", unit);
  2465. return;
  2466. }
  2467. #ifdef HAVE_PPSAPI
  2468. if (parse->flags & PARSE_PPSCLOCK)
  2469. {
  2470. (void)time_pps_destroy(parse->atom.handle);
  2471. }
  2472. #endif
  2473. if (parse->generic->io.fd != parse->ppsfd && parse->ppsfd != -1)
  2474. (void)close(parse->ppsfd); /* close separate PPS source */
  2475. /*
  2476. * print statistics a last time and
  2477. * stop statistics machine
  2478. */
  2479. parse_statistics(parse);
  2480. if (parse->parse_type->cl_end)
  2481. {
  2482. parse->parse_type->cl_end(parse);
  2483. }
  2484. /*
  2485. * cleanup before leaving this world
  2486. */
  2487. if (parse->binding)
  2488. PARSE_END(parse);
  2489. /*
  2490. * Tell the I/O module to turn us off. We're history.
  2491. */
  2492. io_closeclock(&parse->generic->io);
  2493. free_varlist(parse->kv);
  2494. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  2495. msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
  2496. CLK_UNIT(parse->peer), parse->parse_type->cl_description);
  2497. parse->peer = (struct peer *)0; /* unused now */
  2498. peer->procptr->unitptr = (caddr_t)0;
  2499. free(parse);
  2500. }
  2501. #ifdef HAVE_PPSAPI
  2502. /*----------------------------------------
  2503. * set up HARDPPS via PPSAPI
  2504. */
  2505. static void
  2506. parse_hardpps(
  2507. struct parseunit *parse,
  2508. int mode
  2509. )
  2510. {
  2511. if (parse->hardppsstate == mode)
  2512. return;
  2513. if (CLK_PPS(parse->peer) && (parse->flags & PARSE_PPSKERNEL)) {
  2514. int i = 0;
  2515. if (mode == PARSE_HARDPPS_ENABLE)
  2516. {
  2517. if (parse->flags & PARSE_CLEAR)
  2518. i = PPS_CAPTURECLEAR;
  2519. else
  2520. i = PPS_CAPTUREASSERT;
  2521. }
  2522. if (time_pps_kcbind(parse->atom.handle, PPS_KC_HARDPPS, i,
  2523. PPS_TSFMT_TSPEC) < 0) {
  2524. msyslog(LOG_ERR, "PARSE receiver #%d: time_pps_kcbind failed: %m",
  2525. CLK_UNIT(parse->peer));
  2526. } else {
  2527. NLOG(NLOG_CLOCKINFO)
  2528. msyslog(LOG_INFO, "PARSE receiver #%d: kernel PPS synchronisation %sabled",
  2529. CLK_UNIT(parse->peer), (mode == PARSE_HARDPPS_ENABLE) ? "en" : "dis");
  2530. /*
  2531. * tell the rest, that we have a kernel PPS source, iff we ever enable HARDPPS
  2532. */
  2533. if (mode == PARSE_HARDPPS_ENABLE)
  2534. pps_enable = 1;
  2535. }
  2536. }
  2537. parse->hardppsstate = mode;
  2538. }
  2539. /*----------------------------------------
  2540. * set up PPS via PPSAPI
  2541. */
  2542. static int
  2543. parse_ppsapi(
  2544. struct parseunit *parse
  2545. )
  2546. {
  2547. int cap, mode_ppsoffset;
  2548. char *cp;
  2549. parse->flags &= ~PARSE_PPSCLOCK;
  2550. /*
  2551. * collect PPSAPI offset capability - should move into generic handling
  2552. */
  2553. if (time_pps_getcap(parse->atom.handle, &cap) < 0) {
  2554. msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getcap failed: %m",
  2555. CLK_UNIT(parse->peer));
  2556. return 0;
  2557. }
  2558. /*
  2559. * initialize generic PPSAPI interface
  2560. *
  2561. * we leave out CLK_FLAG3 as time_pps_kcbind()
  2562. * is handled here for now. Ideally this should also
  2563. * be part of the generic PPSAPI interface
  2564. */
  2565. if (!refclock_params(parse->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG4), &parse->atom))
  2566. return 0;
  2567. /* nb. only turn things on, if someone else has turned something
  2568. * on before we get here, leave it alone!
  2569. */
  2570. if (parse->flags & PARSE_CLEAR) {
  2571. cp = "CLEAR";
  2572. mode_ppsoffset = PPS_OFFSETCLEAR;
  2573. } else {
  2574. cp = "ASSERT";
  2575. mode_ppsoffset = PPS_OFFSETASSERT;
  2576. }
  2577. msyslog(LOG_INFO, "PARSE receiver #%d: initializing PPS to %s",
  2578. CLK_UNIT(parse->peer), cp);
  2579. if (!(mode_ppsoffset & cap)) {
  2580. msyslog(LOG_WARNING, "PARSE receiver #%d: Cannot set PPS_%sCLEAR, this will increase jitter (PPS API capabilities=0x%x)",
  2581. CLK_UNIT(parse->peer), cp, cap);
  2582. mode_ppsoffset = 0;
  2583. } else {
  2584. if (mode_ppsoffset == PPS_OFFSETCLEAR)
  2585. {
  2586. parse->atom.pps_params.clear_offset.tv_sec = -parse->ppsphaseadjust;
  2587. parse->atom.pps_params.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
  2588. }
  2589. if (mode_ppsoffset == PPS_OFFSETASSERT)
  2590. {
  2591. parse->atom.pps_params.assert_offset.tv_sec = -parse->ppsphaseadjust;
  2592. parse->atom.pps_params.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
  2593. }
  2594. }
  2595. parse->atom.pps_params.mode |= mode_ppsoffset;
  2596. if (time_pps_setparams(parse->atom.handle, &parse->atom.pps_params) < 0) {
  2597. msyslog(LOG_ERR, "PARSE receiver #%d: FAILED set PPS parameters: %m",
  2598. CLK_UNIT(parse->peer));
  2599. return 0;
  2600. }
  2601. parse->flags |= PARSE_PPSCLOCK;
  2602. return 1;
  2603. }
  2604. #else
  2605. #define parse_hardpps(_PARSE_, _MODE_) /* empty */
  2606. #endif
  2607. /*--------------------------------------------------
  2608. * parse_start - open the PARSE devices and initialize data for processing
  2609. */
  2610. static int
  2611. parse_start(
  2612. int sysunit,
  2613. struct peer *peer
  2614. )
  2615. {
  2616. u_int unit;
  2617. int fd232;
  2618. #ifdef HAVE_TERMIOS
  2619. struct termios tio; /* NEEDED FOR A LONG TIME ! */
  2620. #endif
  2621. #ifdef HAVE_SYSV_TTYS
  2622. struct termio tio; /* NEEDED FOR A LONG TIME ! */
  2623. #endif
  2624. struct parseunit * parse;
  2625. char parsedev[sizeof(PARSEDEVICE)+20];
  2626. char parseppsdev[sizeof(PARSEPPSDEVICE)+20];
  2627. parsectl_t tmp_ctl;
  2628. u_int type;
  2629. /*
  2630. * get out Copyright information once
  2631. */
  2632. if (!notice)
  2633. {
  2634. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  2635. msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2009, Frank Kardel");
  2636. notice = 1;
  2637. }
  2638. type = CLK_TYPE(peer);
  2639. unit = CLK_UNIT(peer);
  2640. if ((type == ~0) || (parse_clockinfo[type].cl_description == (char *)0))
  2641. {
  2642. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
  2643. unit, CLK_REALTYPE(peer), ncltypes-1);
  2644. return 0;
  2645. }
  2646. /*
  2647. * Unit okay, attempt to open the device.
  2648. */
  2649. (void) snprintf(parsedev, sizeof(parsedev), PARSEDEVICE, unit);
  2650. (void) snprintf(parseppsdev, sizeof(parsedev), PARSEPPSDEVICE, unit);
  2651. #ifndef O_NOCTTY
  2652. #define O_NOCTTY 0
  2653. #endif
  2654. fd232 = open(parsedev, O_RDWR | O_NOCTTY
  2655. #ifdef O_NONBLOCK
  2656. | O_NONBLOCK
  2657. #endif
  2658. , 0777);
  2659. if (fd232 == -1)
  2660. {
  2661. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
  2662. return 0;
  2663. }
  2664. parse = (struct parseunit *)emalloc(sizeof(struct parseunit));
  2665. memset((char *)parse, 0, sizeof(struct parseunit));
  2666. parse->generic = peer->procptr; /* link up */
  2667. parse->generic->unitptr = (caddr_t)parse; /* link down */
  2668. /*
  2669. * Set up the structures
  2670. */
  2671. parse->generic->timestarted = current_time;
  2672. parse->lastchange = current_time;
  2673. parse->flags = 0;
  2674. parse->pollneeddata = 0;
  2675. parse->laststatistic = current_time;
  2676. parse->lastformat = (unsigned short)~0; /* assume no format known */
  2677. parse->timedata.parse_status = (unsigned short)~0; /* be sure to mark initial status change */
  2678. parse->lastmissed = 0; /* assume got everything */
  2679. parse->ppsserial = 0;
  2680. parse->ppsfd = -1;
  2681. parse->localdata = (void *)0;
  2682. parse->localstate = 0;
  2683. parse->kv = (struct ctl_var *)0;
  2684. clear_err(parse, ERR_ALL);
  2685. parse->parse_type = &parse_clockinfo[type];
  2686. parse->maxunsync = parse->parse_type->cl_maxunsync;
  2687. parse->generic->fudgetime1 = parse->parse_type->cl_basedelay;
  2688. parse->generic->fudgetime2 = 0.0;
  2689. parse->ppsphaseadjust = parse->generic->fudgetime2;
  2690. parse->generic->clockdesc = parse->parse_type->cl_description;
  2691. peer->rootdelay = parse->parse_type->cl_rootdelay;
  2692. peer->sstclktype = parse->parse_type->cl_type;
  2693. peer->precision = sys_precision;
  2694. peer->stratum = STRATUM_REFCLOCK;
  2695. if (peer->stratum <= 1)
  2696. memmove((char *)&parse->generic->refid, parse->parse_type->cl_id, 4);
  2697. else
  2698. parse->generic->refid = htonl(PARSEHSREFID);
  2699. parse->generic->io.fd = fd232;
  2700. parse->peer = peer; /* marks it also as busy */
  2701. /*
  2702. * configure terminal line
  2703. */
  2704. if (TTY_GETATTR(fd232, &tio) == -1)
  2705. {
  2706. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tio): %m", unit, fd232);
  2707. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2708. return 0;
  2709. }
  2710. else
  2711. {
  2712. #ifndef _PC_VDISABLE
  2713. memset((char *)tio.c_cc, 0, sizeof(tio.c_cc));
  2714. #else
  2715. int disablec;
  2716. errno = 0; /* pathconf can deliver -1 without changing errno ! */
  2717. disablec = fpathconf(parse->generic->io.fd, _PC_VDISABLE);
  2718. if (disablec == -1 && errno)
  2719. {
  2720. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CLK_UNIT(parse->peer));
  2721. memset((char *)tio.c_cc, 0, sizeof(tio.c_cc)); /* best guess */
  2722. }
  2723. else
  2724. if (disablec != -1)
  2725. memset((char *)tio.c_cc, disablec, sizeof(tio.c_cc));
  2726. #endif
  2727. #if defined (VMIN) || defined(VTIME)
  2728. if ((parse_clockinfo[type].cl_lflag & ICANON) == 0)
  2729. {
  2730. #ifdef VMIN
  2731. tio.c_cc[VMIN] = 1;
  2732. #endif
  2733. #ifdef VTIME
  2734. tio.c_cc[VTIME] = 0;
  2735. #endif
  2736. }
  2737. #endif
  2738. tio.c_cflag = parse_clockinfo[type].cl_cflag;
  2739. tio.c_iflag = parse_clockinfo[type].cl_iflag;
  2740. tio.c_oflag = parse_clockinfo[type].cl_oflag;
  2741. tio.c_lflag = parse_clockinfo[type].cl_lflag;
  2742. #ifdef HAVE_TERMIOS
  2743. if ((cfsetospeed(&tio, parse_clockinfo[type].cl_speed) == -1) ||
  2744. (cfsetispeed(&tio, parse_clockinfo[type].cl_speed) == -1))
  2745. {
  2746. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcset{i,o}speed(&tio, speed): %m", unit);
  2747. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2748. return 0;
  2749. }
  2750. #else
  2751. tio.c_cflag |= parse_clockinfo[type].cl_speed;
  2752. #endif
  2753. /*
  2754. * set up pps device
  2755. * if the PARSEPPSDEVICE can be opened that will be used
  2756. * for PPS else PARSEDEVICE will be used
  2757. */
  2758. parse->ppsfd = open(parseppsdev, O_RDWR | O_NOCTTY
  2759. #ifdef O_NONBLOCK
  2760. | O_NONBLOCK
  2761. #endif
  2762. , 0777);
  2763. if (parse->ppsfd == -1)
  2764. {
  2765. parse->ppsfd = fd232;
  2766. }
  2767. /*
  2768. * Linux PPS - the old way
  2769. */
  2770. #if defined(HAVE_TIO_SERIAL_STUFF) /* Linux hack: define PPS interface */
  2771. {
  2772. struct serial_struct ss;
  2773. if (ioctl(parse->ppsfd, TIOCGSERIAL, &ss) < 0 ||
  2774. (
  2775. #ifdef ASYNC_LOW_LATENCY
  2776. ss.flags |= ASYNC_LOW_LATENCY,
  2777. #endif
  2778. #ifndef HAVE_PPSAPI
  2779. #ifdef ASYNC_PPS_CD_NEG
  2780. ss.flags |= ASYNC_PPS_CD_NEG,
  2781. #endif
  2782. #endif
  2783. ioctl(parse->ppsfd, TIOCSSERIAL, &ss)) < 0) {
  2784. msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", parse->ppsfd);
  2785. msyslog(LOG_NOTICE,
  2786. "refclock_parse: optional PPS processing not available");
  2787. } else {
  2788. parse->flags |= PARSE_PPSCLOCK;
  2789. #ifdef ASYNC_PPS_CD_NEG
  2790. NLOG(NLOG_CLOCKINFO)
  2791. msyslog(LOG_INFO,
  2792. "refclock_parse: PPS detection on");
  2793. #endif
  2794. }
  2795. }
  2796. #endif
  2797. /*
  2798. * SUN the Solaris way
  2799. */
  2800. #ifdef HAVE_TIOCSPPS /* SUN PPS support */
  2801. if (CLK_PPS(parse->peer))
  2802. {
  2803. int i = 1;
  2804. if (ioctl(parse->ppsfd, TIOCSPPS, (caddr_t)&i) == 0)
  2805. {
  2806. parse->flags |= PARSE_PPSCLOCK;
  2807. }
  2808. }
  2809. #endif
  2810. /*
  2811. * PPS via PPSAPI
  2812. */
  2813. #if defined(HAVE_PPSAPI)
  2814. parse->hardppsstate = PARSE_HARDPPS_DISABLE;
  2815. if (CLK_PPS(parse->peer))
  2816. {
  2817. if (!refclock_ppsapi(parse->ppsfd, &parse->atom))
  2818. {
  2819. msyslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: could not set up PPS: %m", CLK_UNIT(parse->peer));
  2820. }
  2821. else
  2822. {
  2823. parse_ppsapi(parse);
  2824. }
  2825. }
  2826. #endif
  2827. if (TTY_SETATTR(fd232, &tio) == -1)
  2828. {
  2829. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tio): %m", unit, fd232);
  2830. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2831. return 0;
  2832. }
  2833. }
  2834. /*
  2835. * pick correct input machine
  2836. */
  2837. parse->generic->io.srcclock = (caddr_t)parse;
  2838. parse->generic->io.datalen = 0;
  2839. parse->binding = init_iobinding(parse);
  2840. if (parse->binding == (bind_t *)0)
  2841. {
  2842. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.", CLK_UNIT(parse->peer));
  2843. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2844. return 0; /* well, ok - special initialisation broke */
  2845. }
  2846. parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
  2847. parse->generic->io.io_input = parse->binding->bd_io_input; /* pick correct input routine */
  2848. /*
  2849. * as we always(?) get 8 bit chars we want to be
  2850. * sure, that the upper bits are zero for less
  2851. * than 8 bit I/O - so we pass that information on.
  2852. * note that there can be only one bit count format
  2853. * per file descriptor
  2854. */
  2855. switch (tio.c_cflag & CSIZE)
  2856. {
  2857. case CS5:
  2858. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS5;
  2859. break;
  2860. case CS6:
  2861. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS6;
  2862. break;
  2863. case CS7:
  2864. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS7;
  2865. break;
  2866. case CS8:
  2867. tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS8;
  2868. break;
  2869. }
  2870. if (!PARSE_SETCS(parse, &tmp_ctl))
  2871. {
  2872. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
  2873. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2874. return 0; /* well, ok - special initialisation broke */
  2875. }
  2876. strncpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format, sizeof(tmp_ctl.parseformat.parse_buffer));
  2877. tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
  2878. if (!PARSE_SETFMT(parse, &tmp_ctl))
  2879. {
  2880. msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
  2881. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2882. return 0; /* well, ok - special initialisation broke */
  2883. }
  2884. /*
  2885. * get rid of all IO accumulated so far
  2886. */
  2887. #ifdef HAVE_TERMIOS
  2888. (void) tcflush(parse->generic->io.fd, TCIOFLUSH);
  2889. #else
  2890. #if defined(TCFLSH) && defined(TCIOFLUSH)
  2891. {
  2892. int flshcmd = TCIOFLUSH;
  2893. (void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
  2894. }
  2895. #endif
  2896. #endif
  2897. /*
  2898. * try to do any special initializations
  2899. */
  2900. if (parse->parse_type->cl_init)
  2901. {
  2902. if (parse->parse_type->cl_init(parse))
  2903. {
  2904. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2905. return 0; /* well, ok - special initialisation broke */
  2906. }
  2907. }
  2908. /*
  2909. * Insert in async io device list.
  2910. */
  2911. if (!io_addclock(&parse->generic->io))
  2912. {
  2913. msyslog(LOG_ERR,
  2914. "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
  2915. parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
  2916. return 0;
  2917. }
  2918. /*
  2919. * print out configuration
  2920. */
  2921. NLOG(NLOG_CLOCKINFO)
  2922. {
  2923. /* conditional if clause for conditional syslog */
  2924. msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added",
  2925. CLK_UNIT(parse->peer),
  2926. parse->parse_type->cl_description, parsedev,
  2927. (parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev);
  2928. msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d",
  2929. CLK_UNIT(parse->peer),
  2930. parse->peer->stratum,
  2931. l_mktime(parse->maxunsync), parse->peer->precision);
  2932. msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling",
  2933. CLK_UNIT(parse->peer),
  2934. parse->parse_type->cl_rootdelay,
  2935. parse->generic->fudgetime1,
  2936. parse->ppsphaseadjust,
  2937. parse->binding->bd_description);
  2938. msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
  2939. parse->parse_type->cl_format);
  2940. msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer),
  2941. CLK_PPS(parse->peer) ? "" : "NO ",
  2942. CLK_PPS(parse->peer) ?
  2943. #ifdef PPS_METHOD
  2944. " (implementation " PPS_METHOD ")"
  2945. #else
  2946. ""
  2947. #endif
  2948. : ""
  2949. );
  2950. }
  2951. return 1;
  2952. }
  2953. /*--------------------------------------------------
  2954. * parse_ctl - process changes on flags/time values
  2955. */
  2956. static void
  2957. parse_ctl(
  2958. struct parseunit *parse,
  2959. struct refclockstat *in
  2960. )
  2961. {
  2962. if (in)
  2963. {
  2964. if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
  2965. {
  2966. parse->flags = (parse->flags & ~(CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
  2967. (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4));
  2968. #if defined(HAVE_PPSAPI)
  2969. if (CLK_PPS(parse->peer))
  2970. {
  2971. parse_ppsapi(parse);
  2972. }
  2973. #endif
  2974. }
  2975. if (in->haveflags & CLK_HAVETIME1)
  2976. {
  2977. parse->generic->fudgetime1 = in->fudgetime1;
  2978. msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s",
  2979. CLK_UNIT(parse->peer),
  2980. parse->generic->fudgetime1);
  2981. }
  2982. if (in->haveflags & CLK_HAVETIME2)
  2983. {
  2984. parse->generic->fudgetime2 = in->fudgetime2;
  2985. if (parse->flags & PARSE_TRUSTTIME)
  2986. {
  2987. parse->maxunsync = (u_long)ABS(in->fudgetime2);
  2988. msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s",
  2989. CLK_UNIT(parse->peer),
  2990. l_mktime(parse->maxunsync));
  2991. }
  2992. else
  2993. {
  2994. parse->ppsphaseadjust = in->fudgetime2;
  2995. msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s",
  2996. CLK_UNIT(parse->peer),
  2997. parse->ppsphaseadjust);
  2998. #if defined(HAVE_PPSAPI)
  2999. if (CLK_PPS(parse->peer))
  3000. {
  3001. parse_ppsapi(parse);
  3002. }
  3003. #endif
  3004. }
  3005. }
  3006. }
  3007. }
  3008. /*--------------------------------------------------
  3009. * parse_poll - called by the transmit procedure
  3010. */
  3011. static void
  3012. parse_poll(
  3013. int unit,
  3014. struct peer *peer
  3015. )
  3016. {
  3017. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  3018. if (peer != parse->peer)
  3019. {
  3020. msyslog(LOG_ERR,
  3021. "PARSE receiver #%d: poll: INTERNAL: peer incorrect",
  3022. unit);
  3023. return;
  3024. }
  3025. /*
  3026. * Update clock stat counters
  3027. */
  3028. parse->generic->polls++;
  3029. if (parse->pollneeddata &&
  3030. ((current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll)))))
  3031. {
  3032. /*
  3033. * start worrying when exceeding a poll inteval
  3034. * bad news - didn't get a response last time
  3035. */
  3036. parse->lastmissed = current_time;
  3037. parse_event(parse, CEVNT_TIMEOUT);
  3038. ERR(ERR_NODATA)
  3039. msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer));
  3040. }
  3041. /*
  3042. * we just mark that we want the next sample for the clock filter
  3043. */
  3044. parse->pollneeddata = current_time;
  3045. if (parse->parse_type->cl_poll)
  3046. {
  3047. parse->parse_type->cl_poll(parse);
  3048. }
  3049. cparse_statistics(parse);
  3050. return;
  3051. }
  3052. #define LEN_STATES 300 /* length of state string */
  3053. /*--------------------------------------------------
  3054. * parse_control - set fudge factors, return statistics
  3055. */
  3056. static void
  3057. parse_control(
  3058. int unit,
  3059. struct refclockstat *in,
  3060. struct refclockstat *out,
  3061. struct peer *peer
  3062. )
  3063. {
  3064. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  3065. parsectl_t tmpctl;
  3066. static char outstatus[400]; /* status output buffer */
  3067. if (out)
  3068. {
  3069. out->lencode = 0;
  3070. out->p_lastcode = 0;
  3071. out->kv_list = (struct ctl_var *)0;
  3072. }
  3073. if (!parse || !parse->peer)
  3074. {
  3075. msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
  3076. unit);
  3077. return;
  3078. }
  3079. unit = CLK_UNIT(parse->peer);
  3080. /*
  3081. * handle changes
  3082. */
  3083. parse_ctl(parse, in);
  3084. /*
  3085. * supply data
  3086. */
  3087. if (out)
  3088. {
  3089. u_long sum = 0;
  3090. char *tt, *start;
  3091. int i;
  3092. outstatus[0] = '\0';
  3093. out->type = REFCLK_PARSE;
  3094. /*
  3095. * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1
  3096. */
  3097. parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust;
  3098. /*
  3099. * figure out skew between PPS and RS232 - just for informational
  3100. * purposes
  3101. */
  3102. if (PARSE_SYNC(parse->timedata.parse_state))
  3103. {
  3104. if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state))
  3105. {
  3106. l_fp off;
  3107. /*
  3108. * we have a PPS and RS232 signal - calculate the skew
  3109. * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
  3110. */
  3111. off = parse->timedata.parse_stime.fp;
  3112. L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */
  3113. tt = add_var(&out->kv_list, 80, RO);
  3114. snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6));
  3115. }
  3116. }
  3117. if (PARSE_PPS(parse->timedata.parse_state))
  3118. {
  3119. tt = add_var(&out->kv_list, 80, RO|DEF);
  3120. snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp));
  3121. }
  3122. start = tt = add_var(&out->kv_list, 128, RO|DEF);
  3123. snprintf(tt, 128, "refclock_time=\"");
  3124. tt += strlen(tt);
  3125. if (parse->timedata.parse_time.fp.l_ui == 0)
  3126. {
  3127. strncpy(tt, "<UNDEFINED>\"", BUFFER_SIZES(start, tt, 128));
  3128. }
  3129. else
  3130. {
  3131. snprintf(tt, 128, "%s\"", gmprettydate(&parse->timedata.parse_time.fp));
  3132. }
  3133. if (!PARSE_GETTIMECODE(parse, &tmpctl))
  3134. {
  3135. ERR(ERR_INTERNAL)
  3136. msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
  3137. }
  3138. else
  3139. {
  3140. start = tt = add_var(&out->kv_list, 512, RO|DEF);
  3141. snprintf(tt, 512, "refclock_status=\"");
  3142. tt += strlen(tt);
  3143. /*
  3144. * copy PPS flags from last read transaction (informational only)
  3145. */
  3146. tmpctl.parsegettc.parse_state |= parse->timedata.parse_state &
  3147. (PARSEB_PPS|PARSEB_S_PPS);
  3148. (void) parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512));
  3149. strncat(tt, "\"", BUFFER_SIZES(start, tt, 512));
  3150. if (tmpctl.parsegettc.parse_count)
  3151. mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
  3152. tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count));
  3153. }
  3154. tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
  3155. if (!PARSE_GETFMT(parse, &tmpctl))
  3156. {
  3157. ERR(ERR_INTERNAL)
  3158. msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
  3159. }
  3160. else
  3161. {
  3162. tt = add_var(&out->kv_list, 80, RO|DEF);
  3163. snprintf(tt, 80, "refclock_format=\"");
  3164. strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
  3165. strncat(tt,"\"", 80);
  3166. }
  3167. /*
  3168. * gather state statistics
  3169. */
  3170. start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
  3171. strncpy(tt, "refclock_states=\"", LEN_STATES);
  3172. tt += strlen(tt);
  3173. for (i = 0; i <= CEVNT_MAX; i++)
  3174. {
  3175. u_long s_time;
  3176. u_long d = current_time - parse->generic->timestarted;
  3177. u_long percent;
  3178. percent = s_time = PARSE_STATETIME(parse, i);
  3179. while (((u_long)(~0) / 10000) < percent)
  3180. {
  3181. percent /= 10;
  3182. d /= 10;
  3183. }
  3184. if (d)
  3185. percent = (percent * 10000) / d;
  3186. else
  3187. percent = 10000;
  3188. if (s_time)
  3189. {
  3190. char item[80];
  3191. int count;
  3192. snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)",
  3193. sum ? "; " : "",
  3194. (parse->generic->currentstatus == i) ? "*" : "",
  3195. clockstatus((unsigned int)i),
  3196. l_mktime(s_time),
  3197. (int)(percent / 100), (int)(percent % 100));
  3198. if ((count = strlen(item)) < (LEN_STATES - 40 - (tt - start)))
  3199. {
  3200. strncpy(tt, item, BUFFER_SIZES(start, tt, LEN_STATES));
  3201. tt += count;
  3202. }
  3203. sum += s_time;
  3204. }
  3205. }
  3206. snprintf(tt, BUFFER_SIZES(start, tt, LEN_STATES), "; running time: %s\"", l_mktime(sum));
  3207. tt = add_var(&out->kv_list, 32, RO);
  3208. snprintf(tt, 32, "refclock_id=\"%s\"", parse->parse_type->cl_id);
  3209. tt = add_var(&out->kv_list, 80, RO);
  3210. snprintf(tt, 80, "refclock_iomode=\"%s\"", parse->binding->bd_description);
  3211. tt = add_var(&out->kv_list, 128, RO);
  3212. snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid);
  3213. {
  3214. struct ctl_var *k;
  3215. k = parse->kv;
  3216. while (k && !(k->flags & EOV))
  3217. {
  3218. set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags);
  3219. k++;
  3220. }
  3221. }
  3222. out->lencode = strlen(outstatus);
  3223. out->p_lastcode = outstatus;
  3224. }
  3225. }
  3226. /**===========================================================================
  3227. ** processing routines
  3228. **/
  3229. /*--------------------------------------------------
  3230. * event handling - note that nominal events will also be posted
  3231. * keep track of state dwelling times
  3232. */
  3233. static void
  3234. parse_event(
  3235. struct parseunit *parse,
  3236. int event
  3237. )
  3238. {
  3239. if (parse->generic->currentstatus != (u_char) event)
  3240. {
  3241. parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
  3242. parse->lastchange = current_time;
  3243. if (parse->parse_type->cl_event)
  3244. parse->parse_type->cl_event(parse, event);
  3245. if (event == CEVNT_NOMINAL)
  3246. {
  3247. NLOG(NLOG_CLOCKSTATUS)
  3248. msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
  3249. CLK_UNIT(parse->peer));
  3250. }
  3251. refclock_report(parse->peer, event);
  3252. }
  3253. }
  3254. /*--------------------------------------------------
  3255. * process a PARSE time sample
  3256. */
  3257. static void
  3258. parse_process(
  3259. struct parseunit *parse,
  3260. parsetime_t *parsetime
  3261. )
  3262. {
  3263. l_fp off, rectime, reftime;
  3264. double fudge;
  3265. /*
  3266. * check for changes in conversion status
  3267. * (only one for each new status !)
  3268. */
  3269. if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
  3270. ((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
  3271. (parse->timedata.parse_status != parsetime->parse_status))
  3272. {
  3273. char buffer[400];
  3274. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  3275. msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
  3276. CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer)));
  3277. if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
  3278. {
  3279. /*
  3280. * tell more about the story - list time code
  3281. * there is a slight change for a race condition and
  3282. * the time code might be overwritten by the next packet
  3283. */
  3284. parsectl_t tmpctl;
  3285. if (!PARSE_GETTIMECODE(parse, &tmpctl))
  3286. {
  3287. ERR(ERR_INTERNAL)
  3288. msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer));
  3289. }
  3290. else
  3291. {
  3292. ERR(ERR_BADDATA)
  3293. msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)",
  3294. CLK_UNIT(parse->peer), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1)));
  3295. }
  3296. }
  3297. }
  3298. /*
  3299. * examine status and post appropriate events
  3300. */
  3301. if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
  3302. {
  3303. /*
  3304. * got bad data - tell the rest of the system
  3305. */
  3306. switch (parsetime->parse_status & CVT_MASK)
  3307. {
  3308. case CVT_NONE:
  3309. if ((parsetime->parse_status & CVT_ADDITIONAL) &&
  3310. parse->parse_type->cl_message)
  3311. parse->parse_type->cl_message(parse, parsetime);
  3312. /*
  3313. * save PPS information that comes piggyback
  3314. */
  3315. if (PARSE_PPS(parsetime->parse_state))
  3316. {
  3317. parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  3318. parse->timedata.parse_ptime = parsetime->parse_ptime;
  3319. }
  3320. break; /* well, still waiting - timeout is handled at higher levels */
  3321. case CVT_FAIL:
  3322. if (parsetime->parse_status & CVT_BADFMT)
  3323. {
  3324. parse_event(parse, CEVNT_BADREPLY);
  3325. }
  3326. else
  3327. if (parsetime->parse_status & CVT_BADDATE)
  3328. {
  3329. parse_event(parse, CEVNT_BADDATE);
  3330. }
  3331. else
  3332. if (parsetime->parse_status & CVT_BADTIME)
  3333. {
  3334. parse_event(parse, CEVNT_BADTIME);
  3335. }
  3336. else
  3337. {
  3338. parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
  3339. }
  3340. }
  3341. return; /* skip the rest - useless */
  3342. }
  3343. /*
  3344. * check for format changes
  3345. * (in case somebody has swapped clocks 8-)
  3346. */
  3347. if (parse->lastformat != parsetime->parse_format)
  3348. {
  3349. parsectl_t tmpctl;
  3350. tmpctl.parseformat.parse_format = parsetime->parse_format;
  3351. if (!PARSE_GETFMT(parse, &tmpctl))
  3352. {
  3353. ERR(ERR_INTERNAL)
  3354. msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer));
  3355. }
  3356. else
  3357. {
  3358. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  3359. msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"",
  3360. CLK_UNIT(parse->peer), tmpctl.parseformat.parse_buffer);
  3361. }
  3362. parse->lastformat = parsetime->parse_format;
  3363. }
  3364. /*
  3365. * now, any changes ?
  3366. */
  3367. if ((parse->timedata.parse_state ^ parsetime->parse_state) &
  3368. ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS))
  3369. {
  3370. char tmp1[200];
  3371. char tmp2[200];
  3372. /*
  3373. * something happend - except for PPS events
  3374. */
  3375. (void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1));
  3376. (void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2));
  3377. NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
  3378. msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
  3379. CLK_UNIT(parse->peer), tmp2, tmp1);
  3380. }
  3381. /*
  3382. * carry on PPS information if still usable
  3383. */
  3384. if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state))
  3385. {
  3386. parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS;
  3387. parsetime->parse_ptime = parse->timedata.parse_ptime;
  3388. }
  3389. /*
  3390. * remember for future
  3391. */
  3392. parse->timedata = *parsetime;
  3393. /*
  3394. * check to see, whether the clock did a complete powerup or lost PZF signal
  3395. * and post correct events for current condition
  3396. */
  3397. if (PARSE_POWERUP(parsetime->parse_state))
  3398. {
  3399. /*
  3400. * this is bad, as we have completely lost synchronisation
  3401. * well this is a problem with the receiver here
  3402. * for PARSE Meinberg DCF77 receivers the lost synchronisation
  3403. * is true as it is the powerup state and the time is taken
  3404. * from a crude real time clock chip
  3405. * for the PZF/GPS series this is only partly true, as
  3406. * PARSE_POWERUP only means that the pseudo random
  3407. * phase shift sequence cannot be found. this is only
  3408. * bad, if we have never seen the clock in the SYNC
  3409. * state, where the PHASE and EPOCH are correct.
  3410. * for reporting events the above business does not
  3411. * really matter, but we can use the time code
  3412. * even in the POWERUP state after having seen
  3413. * the clock in the synchronized state (PZF class
  3414. * receivers) unless we have had a telegram disruption
  3415. * after having seen the clock in the SYNC state. we
  3416. * thus require having seen the clock in SYNC state
  3417. * *after* having missed telegrams (noresponse) from
  3418. * the clock. one problem remains: we might use erroneously
  3419. * POWERUP data if the disruption is shorter than 1 polling
  3420. * interval. fortunately powerdowns last usually longer than 64
  3421. * seconds and the receiver is at least 2 minutes in the
  3422. * POWERUP or NOSYNC state before switching to SYNC
  3423. * for GPS receivers this can mean antenna problems and other causes.
  3424. * the additional grace period can be enables by a clock
  3425. * mode having the PARSE_F_POWERUPTRUST flag in cl_flag set.
  3426. */
  3427. parse_event(parse, CEVNT_FAULT);
  3428. NLOG(NLOG_CLOCKSTATUS)
  3429. ERR(ERR_BADSTATUS)
  3430. msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED/RECEIVER PROBLEMS",
  3431. CLK_UNIT(parse->peer));
  3432. }
  3433. else
  3434. {
  3435. /*
  3436. * we have two states left
  3437. *
  3438. * SYNC:
  3439. * this state means that the EPOCH (timecode) and PHASE
  3440. * information has be read correctly (at least two
  3441. * successive PARSE timecodes were received correctly)
  3442. * this is the best possible state - full trust
  3443. *
  3444. * NOSYNC:
  3445. * The clock should be on phase with respect to the second
  3446. * signal, but the timecode has not been received correctly within
  3447. * at least the last two minutes. this is a sort of half baked state
  3448. * for PARSE Meinberg DCF77 clocks this is bad news (clock running
  3449. * without timecode confirmation)
  3450. * PZF 535 has also no time confirmation, but the phase should be
  3451. * very precise as the PZF signal can be decoded
  3452. */
  3453. if (PARSE_SYNC(parsetime->parse_state))
  3454. {
  3455. /*
  3456. * currently completely synchronized - best possible state
  3457. */
  3458. parse->lastsync = current_time;
  3459. clear_err(parse, ERR_BADSTATUS);
  3460. }
  3461. else
  3462. {
  3463. /*
  3464. * we have had some problems receiving the time code
  3465. */
  3466. parse_event(parse, CEVNT_PROP);
  3467. NLOG(NLOG_CLOCKSTATUS)
  3468. ERR(ERR_BADSTATUS)
  3469. msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED",
  3470. CLK_UNIT(parse->peer));
  3471. }
  3472. }
  3473. fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */
  3474. if (PARSE_TIMECODE(parsetime->parse_state))
  3475. {
  3476. rectime = parsetime->parse_stime.fp;
  3477. off = reftime = parsetime->parse_time.fp;
  3478. L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */
  3479. #ifdef DEBUG
  3480. if (debug > 3)
  3481. printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n",
  3482. CLK_UNIT(parse->peer),
  3483. prettydate(&reftime),
  3484. prettydate(&rectime),
  3485. lfptoa(&off,6));
  3486. #endif
  3487. }
  3488. if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
  3489. {
  3490. l_fp offset;
  3491. double ppsphaseadjust = parse->ppsphaseadjust;
  3492. #ifdef HAVE_PPSAPI
  3493. /*
  3494. * set fudge = 0.0 if already included in PPS time stamps
  3495. */
  3496. if (parse->atom.pps_params.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
  3497. {
  3498. ppsphaseadjust = 0.0;
  3499. }
  3500. #endif
  3501. /*
  3502. * we have a PPS signal - much better than the RS232 stuff (we hope)
  3503. */
  3504. offset = parsetime->parse_ptime.fp;
  3505. #ifdef DEBUG
  3506. if (debug > 3)
  3507. printf("PARSE receiver #%d: PPStime %s\n",
  3508. CLK_UNIT(parse->peer),
  3509. prettydate(&offset));
  3510. #endif
  3511. if (PARSE_TIMECODE(parsetime->parse_state))
  3512. {
  3513. if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
  3514. M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
  3515. {
  3516. fudge = ppsphaseadjust; /* pick PPS fudge factor */
  3517. /*
  3518. * RS232 offsets within [-0.5..0.5[ - take PPS offsets
  3519. */
  3520. if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
  3521. {
  3522. reftime = off = offset;
  3523. if (reftime.l_uf & (unsigned)0x80000000)
  3524. reftime.l_ui++;
  3525. reftime.l_uf = 0;
  3526. /*
  3527. * implied on second offset
  3528. */
  3529. off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
  3530. off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
  3531. }
  3532. else
  3533. {
  3534. /*
  3535. * time code describes pulse
  3536. */
  3537. reftime = off = parsetime->parse_time.fp;
  3538. L_SUB(&off, &offset); /* true offset */
  3539. }
  3540. }
  3541. /*
  3542. * take RS232 offset when PPS when out of bounds
  3543. */
  3544. }
  3545. else
  3546. {
  3547. fudge = ppsphaseadjust; /* pick PPS fudge factor */
  3548. /*
  3549. * Well, no time code to guide us - assume on second pulse
  3550. * and pray, that we are within [-0.5..0.5[
  3551. */
  3552. off = offset;
  3553. reftime = offset;
  3554. if (reftime.l_uf & (unsigned)0x80000000)
  3555. reftime.l_ui++;
  3556. reftime.l_uf = 0;
  3557. /*
  3558. * implied on second offset
  3559. */
  3560. off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
  3561. off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
  3562. }
  3563. }
  3564. else
  3565. {
  3566. if (!PARSE_TIMECODE(parsetime->parse_state))
  3567. {
  3568. /*
  3569. * Well, no PPS, no TIMECODE, no more work ...
  3570. */
  3571. if ((parsetime->parse_status & CVT_ADDITIONAL) &&
  3572. parse->parse_type->cl_message)
  3573. parse->parse_type->cl_message(parse, parsetime);
  3574. return;
  3575. }
  3576. }
  3577. #ifdef DEBUG
  3578. if (debug > 3)
  3579. printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n",
  3580. CLK_UNIT(parse->peer),
  3581. prettydate(&reftime),
  3582. prettydate(&rectime),
  3583. lfptoa(&off,6));
  3584. #endif
  3585. rectime = reftime;
  3586. L_SUB(&rectime, &off); /* just to keep the ntp interface happy */
  3587. #ifdef DEBUG
  3588. if (debug > 3)
  3589. printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n",
  3590. CLK_UNIT(parse->peer),
  3591. prettydate(&reftime),
  3592. prettydate(&rectime));
  3593. #endif
  3594. if ((parsetime->parse_status & CVT_ADDITIONAL) &&
  3595. parse->parse_type->cl_message)
  3596. parse->parse_type->cl_message(parse, parsetime);
  3597. if (PARSE_SYNC(parsetime->parse_state))
  3598. {
  3599. /*
  3600. * log OK status
  3601. */
  3602. parse_event(parse, CEVNT_NOMINAL);
  3603. }
  3604. clear_err(parse, ERR_BADIO);
  3605. clear_err(parse, ERR_BADDATA);
  3606. clear_err(parse, ERR_NODATA);
  3607. clear_err(parse, ERR_INTERNAL);
  3608. /*
  3609. * and now stick it into the clock machine
  3610. * samples are only valid iff lastsync is not too old and
  3611. * we have seen the clock in sync at least once
  3612. * after the last time we didn't see an expected data telegram
  3613. * at startup being not in sync is also bad just like
  3614. * POWERUP state unless PARSE_F_POWERUPTRUST is set
  3615. * see the clock states section above for more reasoning
  3616. */
  3617. if (((current_time - parse->lastsync) > parse->maxunsync) ||
  3618. (parse->lastsync < parse->lastmissed) ||
  3619. ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
  3620. (((parse->parse_type->cl_flags & PARSE_F_POWERUPTRUST) == 0) &&
  3621. PARSE_POWERUP(parsetime->parse_state)))
  3622. {
  3623. parse->generic->leap = LEAP_NOTINSYNC;
  3624. parse->lastsync = 0; /* wait for full sync again */
  3625. }
  3626. else
  3627. {
  3628. if (PARSE_LEAPADD(parsetime->parse_state))
  3629. {
  3630. /*
  3631. * we pick this state also for time code that pass leap warnings
  3632. * without direction information (as earth is currently slowing
  3633. * down).
  3634. */
  3635. parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
  3636. }
  3637. else
  3638. if (PARSE_LEAPDEL(parsetime->parse_state))
  3639. {
  3640. parse->generic->leap = LEAP_DELSECOND;
  3641. }
  3642. else
  3643. {
  3644. parse->generic->leap = LEAP_NOWARNING;
  3645. }
  3646. }
  3647. if (parse->generic->leap != LEAP_NOTINSYNC)
  3648. {
  3649. /*
  3650. * only good/trusted samples are interesting
  3651. */
  3652. #ifdef DEBUG
  3653. if (debug > 2)
  3654. {
  3655. printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
  3656. CLK_UNIT(parse->peer),
  3657. prettydate(&reftime),
  3658. prettydate(&rectime),
  3659. fudge);
  3660. }
  3661. #endif
  3662. parse->generic->lastref = reftime;
  3663. refclock_process_offset(parse->generic, reftime, rectime, fudge);
  3664. #ifdef HAVE_PPSAPI
  3665. /*
  3666. * pass PPS information on to PPS clock
  3667. */
  3668. if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
  3669. {
  3670. /* refclock_pps includes fudgetime1 - we keep the RS232 offset in there :-( */
  3671. double savedtime1 = parse->generic->fudgetime1;
  3672. parse->generic->fudgetime1 = fudge;
  3673. if (refclock_pps(parse->peer, &parse->atom,
  3674. parse->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4))) {
  3675. parse->peer->flags |= FLAG_PPS;
  3676. } else {
  3677. parse->peer->flags &= ~FLAG_PPS;
  3678. }
  3679. parse->generic->fudgetime1 = savedtime1;
  3680. parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
  3681. }
  3682. #endif
  3683. } else {
  3684. parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
  3685. parse->peer->flags &= ~FLAG_PPS;
  3686. }
  3687. /*
  3688. * ready, unless the machine wants a sample or
  3689. * we are in fast startup mode (peer->dist > MAXDISTANCE)
  3690. */
  3691. if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE)
  3692. return;
  3693. parse->pollneeddata = 0;
  3694. parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS);
  3695. refclock_receive(parse->peer);
  3696. }
  3697. /**===========================================================================
  3698. ** special code for special clocks
  3699. **/
  3700. static void
  3701. mk_utcinfo(
  3702. char *t,
  3703. int wnt,
  3704. int wnlsf,
  3705. int dn,
  3706. int dtls,
  3707. int dtlsf,
  3708. int size
  3709. )
  3710. {
  3711. l_fp leapdate;
  3712. char *start = t;
  3713. snprintf(t, size, "current correction %d sec", dtls);
  3714. t += strlen(t);
  3715. if (wnlsf < 990)
  3716. wnlsf += 1024;
  3717. if (wnt < 990)
  3718. wnt += 1024;
  3719. gpstolfp((unsigned short)wnlsf, (unsigned short)dn, 0, &leapdate);
  3720. if ((dtlsf != dtls) &&
  3721. ((wnlsf - wnt) < 52))
  3722. {
  3723. snprintf(t, BUFFER_SIZES(start, t, size), ", next correction %d sec on %s, new GPS-UTC offset %d",
  3724. dtlsf - dtls, gmprettydate(&leapdate), dtlsf);
  3725. }
  3726. else
  3727. {
  3728. snprintf(t, BUFFER_SIZES(start, t, size), ", last correction on %s",
  3729. gmprettydate(&leapdate));
  3730. }
  3731. }
  3732. #ifdef CLOCK_MEINBERG
  3733. /**===========================================================================
  3734. ** Meinberg GPS166/GPS167 support
  3735. **/
  3736. /*------------------------------------------------------------
  3737. * gps16x_message - process GPS16x messages
  3738. */
  3739. static void
  3740. gps16x_message(
  3741. struct parseunit *parse,
  3742. parsetime_t *parsetime
  3743. )
  3744. {
  3745. if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH)
  3746. {
  3747. GPS_MSG_HDR header;
  3748. unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
  3749. #ifdef DEBUG
  3750. if (debug > 2)
  3751. {
  3752. char msgbuffer[600];
  3753. mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1);
  3754. printf("PARSE receiver #%d: received message (%d bytes) >%s<\n",
  3755. CLK_UNIT(parse->peer),
  3756. parsetime->parse_msglen,
  3757. msgbuffer);
  3758. }
  3759. #endif
  3760. get_mbg_header(&bufp, &header);
  3761. if (header.gps_hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) &&
  3762. (header.gps_len == 0 ||
  3763. (header.gps_len < sizeof(parsetime->parse_msg) &&
  3764. header.gps_data_csum == mbg_csum(bufp, header.gps_len))))
  3765. {
  3766. /*
  3767. * clean message
  3768. */
  3769. switch (header.gps_cmd)
  3770. {
  3771. case GPS_SW_REV:
  3772. {
  3773. char buffer[64];
  3774. SW_REV gps_sw_rev;
  3775. get_mbg_sw_rev(&bufp, &gps_sw_rev);
  3776. snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"",
  3777. (gps_sw_rev.code >> 8) & 0xFF,
  3778. gps_sw_rev.code & 0xFF,
  3779. gps_sw_rev.name[0] ? " " : "",
  3780. gps_sw_rev.name);
  3781. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3782. }
  3783. break;
  3784. case GPS_STAT:
  3785. {
  3786. static struct state
  3787. {
  3788. unsigned short flag; /* status flag */
  3789. unsigned const char *string; /* bit name */
  3790. } states[] =
  3791. {
  3792. { TM_ANT_DISCONN, (const unsigned char *)"ANTENNA FAULTY" },
  3793. { TM_SYN_FLAG, (const unsigned char *)"NO SYNC SIGNAL" },
  3794. { TM_NO_SYNC, (const unsigned char *)"NO SYNC POWERUP" },
  3795. { TM_NO_POS, (const unsigned char *)"NO POSITION" },
  3796. { 0, (const unsigned char *)"" }
  3797. };
  3798. unsigned short status;
  3799. struct state *s = states;
  3800. char buffer[512];
  3801. char *p, *b;
  3802. status = get_lsb_short(&bufp);
  3803. snprintf(buffer, sizeof(buffer), "meinberg_gps_status=\"[0x%04x] ", status);
  3804. if (status)
  3805. {
  3806. p = b = buffer + strlen(buffer);
  3807. while (s->flag)
  3808. {
  3809. if (status & s->flag)
  3810. {
  3811. if (p != b)
  3812. {
  3813. *p++ = ',';
  3814. *p++ = ' ';
  3815. }
  3816. strncat(p, (const char *)s->string, sizeof(buffer));
  3817. }
  3818. s++;
  3819. }
  3820. *p++ = '"';
  3821. *p = '\0';
  3822. }
  3823. else
  3824. {
  3825. strncat(buffer, "<OK>\"", sizeof(buffer));
  3826. }
  3827. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3828. }
  3829. break;
  3830. case GPS_POS_XYZ:
  3831. {
  3832. XYZ xyz;
  3833. char buffer[256];
  3834. get_mbg_xyz(&bufp, xyz);
  3835. snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"",
  3836. mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
  3837. mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
  3838. mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
  3839. set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
  3840. }
  3841. break;
  3842. case GPS_POS_LLA:
  3843. {
  3844. LLA lla;
  3845. char buffer[256];
  3846. get_mbg_lla(&bufp, lla);
  3847. snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
  3848. mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
  3849. mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
  3850. mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
  3851. set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
  3852. }
  3853. break;
  3854. case GPS_TZDL:
  3855. break;
  3856. case GPS_PORT_PARM:
  3857. break;
  3858. case GPS_SYNTH:
  3859. break;
  3860. case GPS_ANT_INFO:
  3861. {
  3862. ANT_INFO antinfo;
  3863. char buffer[512];
  3864. char *p;
  3865. get_mbg_antinfo(&bufp, &antinfo);
  3866. snprintf(buffer, sizeof(buffer), "meinberg_antenna_status=\"");
  3867. p = buffer + strlen(buffer);
  3868. switch (antinfo.status)
  3869. {
  3870. case ANT_INVALID:
  3871. strncat(p, "<OK>", BUFFER_SIZE(buffer, p));
  3872. p += strlen(p);
  3873. break;
  3874. case ANT_DISCONN:
  3875. strncat(p, "DISCONNECTED since ", BUFFER_SIZE(buffer, p));
  3876. NLOG(NLOG_CLOCKSTATUS)
  3877. ERR(ERR_BADSTATUS)
  3878. msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
  3879. CLK_UNIT(parse->peer), p);
  3880. p += strlen(p);
  3881. mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
  3882. *p = '\0';
  3883. break;
  3884. case ANT_RECONN:
  3885. strncat(p, "RECONNECTED on ", BUFFER_SIZE(buffer, p));
  3886. p += strlen(p);
  3887. mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p));
  3888. snprintf(p, BUFFER_SIZE(buffer, p), ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
  3889. (antinfo.delta_t < 0) ? '-' : '+',
  3890. ABS(antinfo.delta_t) / 10000,
  3891. ABS(antinfo.delta_t) % 10000);
  3892. p += strlen(p);
  3893. mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
  3894. *p = '\0';
  3895. break;
  3896. default:
  3897. snprintf(p, BUFFER_SIZE(buffer, p), "bad status 0x%04x", antinfo.status);
  3898. p += strlen(p);
  3899. break;
  3900. }
  3901. strncat(p, "\"", BUFFER_SIZE(buffer, p));
  3902. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  3903. }
  3904. break;
  3905. case GPS_UCAP:
  3906. break;
  3907. case GPS_CFGH:
  3908. {
  3909. CFGH cfgh;
  3910. char buffer[512];
  3911. char *p;
  3912. get_mbg_cfgh(&bufp, &cfgh);
  3913. if (cfgh.valid)
  3914. {
  3915. int i;
  3916. p = buffer;
  3917. strncpy(buffer, "gps_tot_51=\"", BUFFER_SIZE(buffer, p));
  3918. p += strlen(p);
  3919. mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p));
  3920. strncpy(p, "\"", BUFFER_SIZE(buffer, p));
  3921. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3922. p = buffer;
  3923. strncpy(buffer, "gps_tot_63=\"", BUFFER_SIZE(buffer, p));
  3924. p += strlen(p);
  3925. mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p));
  3926. strncpy(p, "\"", BUFFER_SIZE(buffer, p));
  3927. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3928. p = buffer;
  3929. strncpy(buffer, "gps_t0a=\"", BUFFER_SIZE(buffer, p));
  3930. p += strlen(p);
  3931. mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p));
  3932. strncpy(p, "\"", BUFFER_SIZE(buffer, p));
  3933. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3934. for (i = MIN_SVNO; i < MAX_SVNO; i++)
  3935. {
  3936. p = buffer;
  3937. snprintf(p, BUFFER_SIZE(buffer, p), "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
  3938. p += strlen(p);
  3939. switch (cfgh.cfg[i] & 0x7)
  3940. {
  3941. case 0:
  3942. strncpy(p, "BLOCK I", BUFFER_SIZE(buffer, p));
  3943. break;
  3944. case 1:
  3945. strncpy(p, "BLOCK II", BUFFER_SIZE(buffer, p));
  3946. break;
  3947. default:
  3948. strncpy(p, "bad CFG", BUFFER_SIZE(buffer, p));
  3949. break;
  3950. }
  3951. strncat(p, "\"", BUFFER_SIZE(buffer, p));
  3952. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  3953. p = buffer;
  3954. snprintf(p, BUFFER_SIZE(buffer, p), "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
  3955. p += strlen(p);
  3956. switch ((cfgh.health[i] >> 5) & 0x7 )
  3957. {
  3958. case 0:
  3959. strncpy(p, "OK;", BUFFER_SIZE(buffer, p));
  3960. break;
  3961. case 1:
  3962. strncpy(p, "PARITY;", BUFFER_SIZE(buffer, p));
  3963. break;
  3964. case 2:
  3965. strncpy(p, "TLM/HOW;", BUFFER_SIZE(buffer, p));
  3966. break;
  3967. case 3:
  3968. strncpy(p, "Z-COUNT;", BUFFER_SIZE(buffer, p));
  3969. break;
  3970. case 4:
  3971. strncpy(p, "SUBFRAME 1,2,3;", BUFFER_SIZE(buffer, p));
  3972. break;
  3973. case 5:
  3974. strncpy(p, "SUBFRAME 4,5;", BUFFER_SIZE(buffer, p));
  3975. break;
  3976. case 6:
  3977. strncpy(p, "UPLOAD BAD;", BUFFER_SIZE(buffer, p));
  3978. break;
  3979. case 7:
  3980. strncpy(p, "DATA BAD;", BUFFER_SIZE(buffer, p));
  3981. break;
  3982. }
  3983. p += strlen(p);
  3984. switch (cfgh.health[i] & 0x1F)
  3985. {
  3986. case 0:
  3987. strncpy(p, "SIGNAL OK", BUFFER_SIZE(buffer, p));
  3988. break;
  3989. case 0x1C:
  3990. strncpy(p, "SV TEMP OUT", BUFFER_SIZE(buffer, p));
  3991. break;
  3992. case 0x1D:
  3993. strncpy(p, "SV WILL BE TEMP OUT", BUFFER_SIZE(buffer, p));
  3994. break;
  3995. case 0x1E:
  3996. break;
  3997. case 0x1F:
  3998. strncpy(p, "MULTIPLE ERRS", BUFFER_SIZE(buffer, p));
  3999. break;
  4000. default:
  4001. strncpy(p, "TRANSMISSION PROBLEMS", BUFFER_SIZE(buffer, p));
  4002. break;
  4003. }
  4004. strncat(p, "\"", sizeof(buffer));
  4005. set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
  4006. }
  4007. }
  4008. }
  4009. break;
  4010. case GPS_ALM:
  4011. break;
  4012. case GPS_EPH:
  4013. break;
  4014. case GPS_UTC:
  4015. {
  4016. UTC utc;
  4017. char buffer[512];
  4018. char *p;
  4019. p = buffer;
  4020. get_mbg_utc(&bufp, &utc);
  4021. if (utc.valid)
  4022. {
  4023. strncpy(p, "gps_utc_correction=\"", sizeof(buffer));
  4024. p += strlen(p);
  4025. mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p));
  4026. strncat(p, "\"", BUFFER_SIZE(buffer, p));
  4027. }
  4028. else
  4029. {
  4030. strncpy(p, "gps_utc_correction=\"<NO UTC DATA>\"", BUFFER_SIZE(buffer, p));
  4031. }
  4032. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  4033. }
  4034. break;
  4035. case GPS_IONO:
  4036. break;
  4037. case GPS_ASCII_MSG:
  4038. {
  4039. ASCII_MSG gps_ascii_msg;
  4040. char buffer[128];
  4041. get_mbg_ascii_msg(&bufp, &gps_ascii_msg);
  4042. if (gps_ascii_msg.valid)
  4043. {
  4044. char buffer1[128];
  4045. mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
  4046. snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1);
  4047. }
  4048. else
  4049. strncpy(buffer, "gps_message=<NONE>", sizeof(buffer));
  4050. set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
  4051. }
  4052. break;
  4053. default:
  4054. break;
  4055. }
  4056. }
  4057. else
  4058. {
  4059. 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)",
  4060. CLK_UNIT(parse->peer),
  4061. header.gps_hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6),
  4062. header.gps_len,
  4063. header.gps_data_csum, mbg_csum(bufp, (unsigned)((header.gps_len < sizeof(parsetime->parse_msg)) ? header.gps_len : 0)));
  4064. }
  4065. }
  4066. return;
  4067. }
  4068. /*------------------------------------------------------------
  4069. * gps16x_poll - query the reciver peridically
  4070. */
  4071. static void
  4072. gps16x_poll(
  4073. struct peer *peer
  4074. )
  4075. {
  4076. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  4077. static GPS_MSG_HDR sequence[] =
  4078. {
  4079. { GPS_SW_REV, 0, 0, 0 },
  4080. { GPS_STAT, 0, 0, 0 },
  4081. { GPS_UTC, 0, 0, 0 },
  4082. { GPS_ASCII_MSG, 0, 0, 0 },
  4083. { GPS_ANT_INFO, 0, 0, 0 },
  4084. { GPS_CFGH, 0, 0, 0 },
  4085. { GPS_POS_XYZ, 0, 0, 0 },
  4086. { GPS_POS_LLA, 0, 0, 0 },
  4087. { (unsigned short)~0, 0, 0, 0 }
  4088. };
  4089. int rtc;
  4090. unsigned char cmd_buffer[64];
  4091. unsigned char *outp = cmd_buffer;
  4092. GPS_MSG_HDR *header;
  4093. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4094. {
  4095. parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
  4096. }
  4097. if (sequence[parse->localstate].gps_cmd == (unsigned short)~0)
  4098. parse->localstate = 0;
  4099. header = sequence + parse->localstate++;
  4100. *outp++ = SOH; /* start command */
  4101. put_mbg_header(&outp, header);
  4102. outp = cmd_buffer + 1;
  4103. header->gps_hdr_csum = (short)mbg_csum(outp, 6);
  4104. put_mbg_header(&outp, header);
  4105. #ifdef DEBUG
  4106. if (debug > 2)
  4107. {
  4108. char buffer[128];
  4109. mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1);
  4110. printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n",
  4111. CLK_UNIT(parse->peer),
  4112. parse->localstate - 1,
  4113. (int)(outp - cmd_buffer),
  4114. buffer);
  4115. }
  4116. #endif
  4117. rtc = write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer));
  4118. if (rtc < 0)
  4119. {
  4120. ERR(ERR_BADIO)
  4121. msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4122. }
  4123. else
  4124. if (rtc != outp - cmd_buffer)
  4125. {
  4126. ERR(ERR_BADIO)
  4127. 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));
  4128. }
  4129. clear_err(parse, ERR_BADIO);
  4130. return;
  4131. }
  4132. /*--------------------------------------------------
  4133. * init routine - setup timer
  4134. */
  4135. static int
  4136. gps16x_poll_init(
  4137. struct parseunit *parse
  4138. )
  4139. {
  4140. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4141. {
  4142. parse->peer->action = gps16x_poll;
  4143. gps16x_poll(parse->peer);
  4144. }
  4145. return 0;
  4146. }
  4147. #else
  4148. static void
  4149. gps16x_message(
  4150. struct parseunit *parse,
  4151. parsetime_t *parsetime
  4152. )
  4153. {}
  4154. static int
  4155. gps16x_poll_init(
  4156. struct parseunit *parse
  4157. )
  4158. {
  4159. return 1;
  4160. }
  4161. #endif /* CLOCK_MEINBERG */
  4162. /**===========================================================================
  4163. ** clock polling support
  4164. **/
  4165. /*--------------------------------------------------
  4166. * direct poll routine
  4167. */
  4168. static void
  4169. poll_dpoll(
  4170. struct parseunit *parse
  4171. )
  4172. {
  4173. int rtc;
  4174. const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
  4175. int ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
  4176. rtc = write(parse->generic->io.fd, ps, (unsigned long)ct);
  4177. if (rtc < 0)
  4178. {
  4179. ERR(ERR_BADIO)
  4180. msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4181. }
  4182. else
  4183. if (rtc != ct)
  4184. {
  4185. ERR(ERR_BADIO)
  4186. msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, ct);
  4187. }
  4188. clear_err(parse, ERR_BADIO);
  4189. }
  4190. /*--------------------------------------------------
  4191. * periodic poll routine
  4192. */
  4193. static void
  4194. poll_poll(
  4195. struct peer *peer
  4196. )
  4197. {
  4198. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  4199. if (parse->parse_type->cl_poll)
  4200. parse->parse_type->cl_poll(parse);
  4201. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4202. {
  4203. parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
  4204. }
  4205. }
  4206. /*--------------------------------------------------
  4207. * init routine - setup timer
  4208. */
  4209. static int
  4210. poll_init(
  4211. struct parseunit *parse
  4212. )
  4213. {
  4214. if (((poll_info_t *)parse->parse_type->cl_data)->rate)
  4215. {
  4216. parse->peer->action = poll_poll;
  4217. poll_poll(parse->peer);
  4218. }
  4219. return 0;
  4220. }
  4221. /**===========================================================================
  4222. ** Trimble support
  4223. **/
  4224. /*-------------------------------------------------------------
  4225. * trimble TAIP init routine - setup EOL and then do poll_init.
  4226. */
  4227. static int
  4228. trimbletaip_init(
  4229. struct parseunit *parse
  4230. )
  4231. {
  4232. #ifdef HAVE_TERMIOS
  4233. struct termios tio;
  4234. #endif
  4235. #ifdef HAVE_SYSV_TTYS
  4236. struct termio tio;
  4237. #endif
  4238. /*
  4239. * configure terminal line for trimble receiver
  4240. */
  4241. if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
  4242. {
  4243. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
  4244. return 0;
  4245. }
  4246. else
  4247. {
  4248. tio.c_cc[VEOL] = TRIMBLETAIP_EOL;
  4249. if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
  4250. {
  4251. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
  4252. return 0;
  4253. }
  4254. }
  4255. return poll_init(parse);
  4256. }
  4257. /*--------------------------------------------------
  4258. * trimble TAIP event routine - reset receiver upon data format trouble
  4259. */
  4260. static const char *taipinit[] = {
  4261. ">FPV00000000<",
  4262. ">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<",
  4263. ">FTM00020001<",
  4264. (char *)0
  4265. };
  4266. static void
  4267. trimbletaip_event(
  4268. struct parseunit *parse,
  4269. int event
  4270. )
  4271. {
  4272. switch (event)
  4273. {
  4274. case CEVNT_BADREPLY: /* reset on garbled input */
  4275. case CEVNT_TIMEOUT: /* reset on no input */
  4276. {
  4277. const char **iv;
  4278. iv = taipinit;
  4279. while (*iv)
  4280. {
  4281. int rtc = write(parse->generic->io.fd, *iv, strlen(*iv));
  4282. if (rtc < 0)
  4283. {
  4284. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4285. return;
  4286. }
  4287. else
  4288. {
  4289. if (rtc != strlen(*iv))
  4290. {
  4291. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)",
  4292. CLK_UNIT(parse->peer), rtc, (int)strlen(*iv));
  4293. return;
  4294. }
  4295. }
  4296. iv++;
  4297. }
  4298. NLOG(NLOG_CLOCKINFO)
  4299. ERR(ERR_BADIO)
  4300. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED",
  4301. CLK_UNIT(parse->peer));
  4302. }
  4303. break;
  4304. default: /* ignore */
  4305. break;
  4306. }
  4307. }
  4308. /*
  4309. * This driver supports the Trimble SVee Six Plus GPS receiver module.
  4310. * It should support other Trimble receivers which use the Trimble Standard
  4311. * Interface Protocol (see below).
  4312. *
  4313. * The module has a serial I/O port for command/data and a 1 pulse-per-second
  4314. * output, about 1 microsecond wide. The leading edge of the pulse is
  4315. * coincident with the change of the GPS second. This is the same as
  4316. * the change of the UTC second +/- ~1 microsecond. Some other clocks
  4317. * specifically use a feature in the data message as a timing reference, but
  4318. * the SVee Six Plus does not do this. In fact there is considerable jitter
  4319. * on the timing of the messages, so this driver only supports the use
  4320. * of the PPS pulse for accurate timing. Where it is determined that
  4321. * the offset is way off, when first starting up ntpd for example,
  4322. * the timing of the data stream is used until the offset becomes low enough
  4323. * (|offset| < CLOCK_MAX), at which point the pps offset is used.
  4324. *
  4325. * It can use either option for receiving PPS information - the 'ppsclock'
  4326. * stream pushed onto the serial data interface to timestamp the Carrier
  4327. * Detect interrupts, where the 1PPS connects to the CD line. This only
  4328. * works on SunOS 4.1.x currently. To select this, define PPSPPS in
  4329. * Config.local. The other option is to use a pulse-stretcher/level-converter
  4330. * to convert the PPS pulse into a RS232 start pulse & feed this into another
  4331. * tty port. To use this option, define PPSCLK in Config.local. The pps input,
  4332. * by whichever method, is handled in ntp_loopfilter.c
  4333. *
  4334. * The receiver uses a serial message protocol called Trimble Standard
  4335. * Interface Protocol (it can support others but this driver only supports
  4336. * TSIP). Messages in this protocol have the following form:
  4337. *
  4338. * <DLE><id> ... <data> ... <DLE><ETX>
  4339. *
  4340. * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
  4341. * on transmission and compressed back to one on reception. Otherwise
  4342. * the values of data bytes can be anything. The serial interface is RS-422
  4343. * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
  4344. * in total!), and 1 stop bit. The protocol supports byte, integer, single,
  4345. * and double datatypes. Integers are two bytes, sent most significant first.
  4346. * Singles are IEEE754 single precision floating point numbers (4 byte) sent
  4347. * sign & exponent first. Doubles are IEEE754 double precision floating point
  4348. * numbers (8 byte) sent sign & exponent first.
  4349. * The receiver supports a large set of messages, only a small subset of
  4350. * which are used here. From driver to receiver the following are used:
  4351. *
  4352. * ID Description
  4353. *
  4354. * 21 Request current time
  4355. * 22 Mode Select
  4356. * 2C Set/Request operating parameters
  4357. * 2F Request UTC info
  4358. * 35 Set/Request I/O options
  4359. * From receiver to driver the following are recognised:
  4360. *
  4361. * ID Description
  4362. *
  4363. * 41 GPS Time
  4364. * 44 Satellite selection, PDOP, mode
  4365. * 46 Receiver health
  4366. * 4B Machine code/status
  4367. * 4C Report operating parameters (debug only)
  4368. * 4F UTC correction data (used to get leap second warnings)
  4369. * 55 I/O options (debug only)
  4370. *
  4371. * All others are accepted but ignored.
  4372. *
  4373. */
  4374. #define PI 3.1415926535898 /* lots of sig figs */
  4375. #define D2R PI/180.0
  4376. /*-------------------------------------------------------------------
  4377. * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command
  4378. * interface to the receiver.
  4379. *
  4380. * CAVEAT: the sendflt, sendint routines are byte order dependend and
  4381. * float implementation dependend - these must be converted to portable
  4382. * versions !
  4383. *
  4384. * CURRENT LIMITATION: float implementation. This runs only on systems
  4385. * with IEEE754 floats as native floats
  4386. */
  4387. typedef struct trimble
  4388. {
  4389. u_long last_msg; /* last message received */
  4390. u_long last_reset; /* last time a reset was issued */
  4391. u_char qtracking; /* query tracking status */
  4392. u_long ctrack; /* current tracking set */
  4393. u_long ltrack; /* last tracking set */
  4394. } trimble_t;
  4395. union uval {
  4396. u_char bd[8];
  4397. int iv;
  4398. float fv;
  4399. double dv;
  4400. };
  4401. struct txbuf
  4402. {
  4403. short idx; /* index to first unused byte */
  4404. u_char *txt; /* pointer to actual data buffer */
  4405. };
  4406. void sendcmd (struct txbuf *buf, int c);
  4407. void sendbyte (struct txbuf *buf, int b);
  4408. void sendetx (struct txbuf *buf, struct parseunit *parse);
  4409. void sendint (struct txbuf *buf, int a);
  4410. void sendflt (struct txbuf *buf, double a);
  4411. void
  4412. sendcmd(
  4413. struct txbuf *buf,
  4414. int c
  4415. )
  4416. {
  4417. buf->txt[0] = DLE;
  4418. buf->txt[1] = (u_char)c;
  4419. buf->idx = 2;
  4420. }
  4421. void sendcmd (struct txbuf *buf, int c);
  4422. void sendbyte (struct txbuf *buf, int b);
  4423. void sendetx (struct txbuf *buf, struct parseunit *parse);
  4424. void sendint (struct txbuf *buf, int a);
  4425. void sendflt (struct txbuf *buf, double a);
  4426. void
  4427. sendbyte(
  4428. struct txbuf *buf,
  4429. int b
  4430. )
  4431. {
  4432. if (b == DLE)
  4433. buf->txt[buf->idx++] = DLE;
  4434. buf->txt[buf->idx++] = (u_char)b;
  4435. }
  4436. void
  4437. sendetx(
  4438. struct txbuf *buf,
  4439. struct parseunit *parse
  4440. )
  4441. {
  4442. buf->txt[buf->idx++] = DLE;
  4443. buf->txt[buf->idx++] = ETX;
  4444. if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx)
  4445. {
  4446. ERR(ERR_BADIO)
  4447. msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
  4448. }
  4449. else
  4450. {
  4451. #ifdef DEBUG
  4452. if (debug > 2)
  4453. {
  4454. char buffer[256];
  4455. mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1);
  4456. printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n",
  4457. CLK_UNIT(parse->peer),
  4458. buf->idx, buffer);
  4459. }
  4460. #endif
  4461. clear_err(parse, ERR_BADIO);
  4462. }
  4463. }
  4464. void
  4465. sendint(
  4466. struct txbuf *buf,
  4467. int a
  4468. )
  4469. {
  4470. /* send 16bit int, msbyte first */
  4471. sendbyte(buf, (u_char)((a>>8) & 0xff));
  4472. sendbyte(buf, (u_char)(a & 0xff));
  4473. }
  4474. void
  4475. sendflt(
  4476. struct txbuf *buf,
  4477. double a
  4478. )
  4479. {
  4480. int i;
  4481. union uval uval;
  4482. uval.fv = a;
  4483. #ifdef WORDS_BIGENDIAN
  4484. for (i=0; i<=3; i++)
  4485. #else
  4486. for (i=3; i>=0; i--)
  4487. #endif
  4488. sendbyte(buf, uval.bd[i]);
  4489. }
  4490. #define TRIM_POS_OPT 0x13 /* output position with high precision */
  4491. #define TRIM_TIME_OPT 0x03 /* use UTC time stamps, on second */
  4492. /*--------------------------------------------------
  4493. * trimble TSIP setup routine
  4494. */
  4495. static int
  4496. trimbletsip_setup(
  4497. struct parseunit *parse,
  4498. const char *reason
  4499. )
  4500. {
  4501. u_char buffer[256];
  4502. struct txbuf buf;
  4503. trimble_t *t = parse->localdata;
  4504. if (t && t->last_reset &&
  4505. ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) {
  4506. return 1; /* not yet */
  4507. }
  4508. if (t)
  4509. t->last_reset = current_time;
  4510. buf.txt = buffer;
  4511. sendcmd(&buf, CMD_CVERSION); /* request software versions */
  4512. sendetx(&buf, parse);
  4513. sendcmd(&buf, CMD_COPERPARAM); /* set operating parameters */
  4514. sendbyte(&buf, 4); /* static */
  4515. sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */
  4516. sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */
  4517. sendflt(&buf, 12.0); /* PDOP mask = 12 */
  4518. sendflt(&buf, 8.0); /* PDOP switch level = 8 */
  4519. sendetx(&buf, parse);
  4520. sendcmd(&buf, CMD_CMODESEL); /* fix mode select */
  4521. sendbyte(&buf, 1); /* time transfer mode */
  4522. sendetx(&buf, parse);
  4523. sendcmd(&buf, CMD_CMESSAGE); /* request system message */
  4524. sendetx(&buf, parse);
  4525. sendcmd(&buf, CMD_CSUPER); /* superpacket fix */
  4526. sendbyte(&buf, 0x2); /* binary mode */
  4527. sendetx(&buf, parse);
  4528. sendcmd(&buf, CMD_CIOOPTIONS); /* set I/O options */
  4529. sendbyte(&buf, TRIM_POS_OPT); /* position output */
  4530. sendbyte(&buf, 0x00); /* no velocity output */
  4531. sendbyte(&buf, TRIM_TIME_OPT); /* UTC, compute on seconds */
  4532. sendbyte(&buf, 0x00); /* no raw measurements */
  4533. sendetx(&buf, parse);
  4534. sendcmd(&buf, CMD_CUTCPARAM); /* request UTC correction data */
  4535. sendetx(&buf, parse);
  4536. NLOG(NLOG_CLOCKINFO)
  4537. ERR(ERR_BADIO)
  4538. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason);
  4539. return 0;
  4540. }
  4541. /*--------------------------------------------------
  4542. * TRIMBLE TSIP check routine
  4543. */
  4544. static void
  4545. trimble_check(
  4546. struct peer *peer
  4547. )
  4548. {
  4549. struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
  4550. trimble_t *t = parse->localdata;
  4551. u_char buffer[256];
  4552. struct txbuf buf;
  4553. buf.txt = buffer;
  4554. if (t)
  4555. {
  4556. if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
  4557. (void)trimbletsip_setup(parse, "message timeout");
  4558. }
  4559. poll_poll(parse->peer); /* emit query string and re-arm timer */
  4560. if (t && t->qtracking)
  4561. {
  4562. u_long oldsats = t->ltrack & ~t->ctrack;
  4563. t->qtracking = 0;
  4564. t->ltrack = t->ctrack;
  4565. if (oldsats)
  4566. {
  4567. int i;
  4568. for (i = 0; oldsats; i++) {
  4569. if (oldsats & (1 << i))
  4570. {
  4571. sendcmd(&buf, CMD_CSTATTRACK);
  4572. sendbyte(&buf, i+1); /* old sat */
  4573. sendetx(&buf, parse);
  4574. }
  4575. oldsats &= ~(1 << i);
  4576. }
  4577. }
  4578. sendcmd(&buf, CMD_CSTATTRACK);
  4579. sendbyte(&buf, 0x00); /* current tracking set */
  4580. sendetx(&buf, parse);
  4581. }
  4582. }
  4583. /*--------------------------------------------------
  4584. * TRIMBLE TSIP end routine
  4585. */
  4586. static void
  4587. trimbletsip_end(
  4588. struct parseunit *parse
  4589. )
  4590. { trimble_t *t = parse->localdata;
  4591. if (t)
  4592. {
  4593. free(t);
  4594. parse->localdata = (void *)0;
  4595. }
  4596. parse->peer->nextaction = 0;
  4597. parse->peer->action = (void (*) (struct peer *))0;
  4598. }
  4599. /*--------------------------------------------------
  4600. * TRIMBLE TSIP init routine
  4601. */
  4602. static int
  4603. trimbletsip_init(
  4604. struct parseunit *parse
  4605. )
  4606. {
  4607. #if defined(VEOL) || defined(VEOL2)
  4608. #ifdef HAVE_TERMIOS
  4609. struct termios tio; /* NEEDED FOR A LONG TIME ! */
  4610. #endif
  4611. #ifdef HAVE_SYSV_TTYS
  4612. struct termio tio; /* NEEDED FOR A LONG TIME ! */
  4613. #endif
  4614. /*
  4615. * allocate local data area
  4616. */
  4617. if (!parse->localdata)
  4618. {
  4619. trimble_t *t;
  4620. t = (trimble_t *)(parse->localdata = emalloc(sizeof(trimble_t)));
  4621. if (t)
  4622. {
  4623. memset((char *)t, 0, sizeof(trimble_t));
  4624. t->last_msg = current_time;
  4625. }
  4626. }
  4627. parse->peer->action = trimble_check;
  4628. parse->peer->nextaction = current_time;
  4629. /*
  4630. * configure terminal line for ICANON mode with VEOL characters
  4631. */
  4632. if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
  4633. {
  4634. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcgetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
  4635. return 0;
  4636. }
  4637. else
  4638. {
  4639. if ((parse_clockinfo[CLK_TYPE(parse->peer)].cl_lflag & ICANON))
  4640. {
  4641. #ifdef VEOL
  4642. tio.c_cc[VEOL] = ETX;
  4643. #endif
  4644. #ifdef VEOL2
  4645. tio.c_cc[VEOL2] = DLE;
  4646. #endif
  4647. }
  4648. if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
  4649. {
  4650. msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcsetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
  4651. return 0;
  4652. }
  4653. }
  4654. #endif
  4655. return trimbletsip_setup(parse, "initial startup");
  4656. }
  4657. /*------------------------------------------------------------
  4658. * trimbletsip_event - handle Trimble events
  4659. * simple evente handler - attempt to re-initialize receiver
  4660. */
  4661. static void
  4662. trimbletsip_event(
  4663. struct parseunit *parse,
  4664. int event
  4665. )
  4666. {
  4667. switch (event)
  4668. {
  4669. case CEVNT_BADREPLY: /* reset on garbled input */
  4670. case CEVNT_TIMEOUT: /* reset on no input */
  4671. (void)trimbletsip_setup(parse, "event BAD_REPLY/TIMEOUT");
  4672. break;
  4673. default: /* ignore */
  4674. break;
  4675. }
  4676. }
  4677. /*
  4678. * getflt, getint convert fields in the incoming data into the
  4679. * appropriate type of item
  4680. *
  4681. * CAVEAT: these routines are currently definitely byte order dependent
  4682. * and assume Representation(float) == IEEE754
  4683. * These functions MUST be converted to portable versions (especially
  4684. * converting the float representation into ntp_fp formats in order
  4685. * to avoid floating point operations at all!
  4686. */
  4687. static float
  4688. getflt(
  4689. u_char *bp
  4690. )
  4691. {
  4692. union uval uval;
  4693. #ifdef WORDS_BIGENDIAN
  4694. uval.bd[0] = *bp++;
  4695. uval.bd[1] = *bp++;
  4696. uval.bd[2] = *bp++;
  4697. uval.bd[3] = *bp;
  4698. #else /* ! WORDS_BIGENDIAN */
  4699. uval.bd[3] = *bp++;
  4700. uval.bd[2] = *bp++;
  4701. uval.bd[1] = *bp++;
  4702. uval.bd[0] = *bp;
  4703. #endif /* ! WORDS_BIGENDIAN */
  4704. return uval.fv;
  4705. }
  4706. static double
  4707. getdbl(
  4708. u_char *bp
  4709. )
  4710. {
  4711. union uval uval;
  4712. #ifdef WORDS_BIGENDIAN
  4713. uval.bd[0] = *bp++;
  4714. uval.bd[1] = *bp++;
  4715. uval.bd[2] = *bp++;
  4716. uval.bd[3] = *bp++;
  4717. uval.bd[4] = *bp++;
  4718. uval.bd[5] = *bp++;
  4719. uval.bd[6] = *bp++;
  4720. uval.bd[7] = *bp;
  4721. #else /* ! WORDS_BIGENDIAN */
  4722. uval.bd[7] = *bp++;
  4723. uval.bd[6] = *bp++;
  4724. uval.bd[5] = *bp++;
  4725. uval.bd[4] = *bp++;
  4726. uval.bd[3] = *bp++;
  4727. uval.bd[2] = *bp++;
  4728. uval.bd[1] = *bp++;
  4729. uval.bd[0] = *bp;
  4730. #endif /* ! WORDS_BIGENDIAN */
  4731. return uval.dv;
  4732. }
  4733. static int
  4734. getshort(
  4735. unsigned char *p
  4736. )
  4737. {
  4738. return get_msb_short(&p);
  4739. }
  4740. /*--------------------------------------------------
  4741. * trimbletsip_message - process trimble messages
  4742. */
  4743. #define RTOD (180.0 / 3.1415926535898)
  4744. #define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */
  4745. static void
  4746. trimbletsip_message(
  4747. struct parseunit *parse,
  4748. parsetime_t *parsetime
  4749. )
  4750. {
  4751. unsigned char *buffer = parsetime->parse_msg;
  4752. unsigned int size = parsetime->parse_msglen;
  4753. if ((size < 4) ||
  4754. (buffer[0] != DLE) ||
  4755. (buffer[size-1] != ETX) ||
  4756. (buffer[size-2] != DLE))
  4757. {
  4758. #ifdef DEBUG
  4759. if (debug > 2) {
  4760. int i;
  4761. printf("TRIMBLE BAD packet, size %d:\n ", size);
  4762. for (i = 0; i < size; i++) {
  4763. printf ("%2.2x, ", buffer[i]&0xff);
  4764. if (i%16 == 15) printf("\n\t");
  4765. }
  4766. printf("\n");
  4767. }
  4768. #endif
  4769. return;
  4770. }
  4771. else
  4772. {
  4773. int var_flag;
  4774. trimble_t *tr = parse->localdata;
  4775. unsigned int cmd = buffer[1];
  4776. char pbuffer[200];
  4777. char *t = pbuffer;
  4778. cmd_info_t *s;
  4779. #ifdef DEBUG
  4780. if (debug > 3) {
  4781. int i;
  4782. printf("TRIMBLE packet 0x%02x, size %d:\n ", cmd, size);
  4783. for (i = 0; i < size; i++) {
  4784. printf ("%2.2x, ", buffer[i]&0xff);
  4785. if (i%16 == 15) printf("\n\t");
  4786. }
  4787. printf("\n");
  4788. }
  4789. #endif
  4790. if (tr)
  4791. tr->last_msg = current_time;
  4792. s = trimble_convert(cmd, trimble_rcmds);
  4793. if (s)
  4794. {
  4795. snprintf(t, BUFFER_SIZE(pbuffer, t), "%s=\"", s->varname);
  4796. }
  4797. else
  4798. {
  4799. DPRINTF(1, ("TRIMBLE UNKNOWN COMMAND 0x%02x\n", cmd));
  4800. return;
  4801. }
  4802. var_flag = s->varmode;
  4803. t += strlen(t);
  4804. switch(cmd)
  4805. {
  4806. case CMD_RCURTIME:
  4807. snprintf(t, BUFFER_SIZE(pbuffer, t), "%f, %d, %f",
  4808. getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
  4809. getflt((unsigned char *)&mb(6)));
  4810. break;
  4811. case CMD_RBEST4:
  4812. strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
  4813. t += strlen(t);
  4814. switch (mb(0) & 0xF)
  4815. {
  4816. default:
  4817. snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
  4818. break;
  4819. case 1:
  4820. strncpy(t, "0D", BUFFER_SIZE(pbuffer, t));
  4821. break;
  4822. case 3:
  4823. strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
  4824. break;
  4825. case 4:
  4826. strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
  4827. break;
  4828. }
  4829. t += strlen(t);
  4830. if (mb(0) & 0x10)
  4831. strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
  4832. else
  4833. strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
  4834. t += strlen(t);
  4835. snprintf(t, BUFFER_SIZE(pbuffer, t), "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
  4836. mb(1), mb(2), mb(3), mb(4),
  4837. getflt((unsigned char *)&mb(5)),
  4838. getflt((unsigned char *)&mb(9)),
  4839. getflt((unsigned char *)&mb(13)),
  4840. getflt((unsigned char *)&mb(17)));
  4841. break;
  4842. case CMD_RVERSION:
  4843. snprintf(t, BUFFER_SIZE(pbuffer, t), "%d.%d (%d/%d/%d)",
  4844. mb(0)&0xff, mb(1)&0xff, 1900+(mb(4)&0xff), mb(2)&0xff, mb(3)&0xff);
  4845. break;
  4846. case CMD_RRECVHEALTH:
  4847. {
  4848. static const char *msgs[] =
  4849. {
  4850. "Battery backup failed",
  4851. "Signal processor error",
  4852. "Alignment error, channel or chip 1",
  4853. "Alignment error, channel or chip 2",
  4854. "Antenna feed line fault",
  4855. "Excessive ref freq. error",
  4856. "<BIT 6>",
  4857. "<BIT 7>"
  4858. };
  4859. int i, bits;
  4860. switch (mb(0) & 0xFF)
  4861. {
  4862. default:
  4863. snprintf(t, BUFFER_SIZE(pbuffer, t), "illegal value 0x%02x", mb(0) & 0xFF);
  4864. break;
  4865. case 0x00:
  4866. strncpy(t, "doing position fixes", BUFFER_SIZE(pbuffer, t));
  4867. break;
  4868. case 0x01:
  4869. strncpy(t, "no GPS time yet", BUFFER_SIZE(pbuffer, t));
  4870. break;
  4871. case 0x03:
  4872. strncpy(t, "PDOP too high", BUFFER_SIZE(pbuffer, t));
  4873. break;
  4874. case 0x08:
  4875. strncpy(t, "no usable satellites", BUFFER_SIZE(pbuffer, t));
  4876. break;
  4877. case 0x09:
  4878. strncpy(t, "only ONE usable satellite", BUFFER_SIZE(pbuffer, t));
  4879. break;
  4880. case 0x0A:
  4881. strncpy(t, "only TWO usable satellites", BUFFER_SIZE(pbuffer, t));
  4882. break;
  4883. case 0x0B:
  4884. strncpy(t, "only THREE usable satellites", BUFFER_SIZE(pbuffer, t));
  4885. break;
  4886. case 0x0C:
  4887. strncpy(t, "the chosen satellite is unusable", BUFFER_SIZE(pbuffer, t));
  4888. break;
  4889. }
  4890. t += strlen(t);
  4891. bits = mb(1) & 0xFF;
  4892. for (i = 0; i < 8; i++)
  4893. if (bits & (0x1<<i))
  4894. {
  4895. snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
  4896. t += strlen(t);
  4897. }
  4898. }
  4899. break;
  4900. case CMD_RMESSAGE:
  4901. mkreadable(t, (int)BUFFER_SIZE(pbuffer, t), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
  4902. break;
  4903. case CMD_RMACHSTAT:
  4904. {
  4905. static const char *msgs[] =
  4906. {
  4907. "Synthesizer Fault",
  4908. "Battery Powered Time Clock Fault",
  4909. "A-to-D Converter Fault",
  4910. "The almanac stored in the receiver is not complete and current",
  4911. "<BIT 4>",
  4912. "<BIT 5",
  4913. "<BIT 6>",
  4914. "<BIT 7>"
  4915. };
  4916. int i, bits;
  4917. snprintf(t, BUFFER_SIZE(pbuffer, t), "machine id 0x%02x", mb(0) & 0xFF);
  4918. t += strlen(t);
  4919. bits = mb(1) & 0xFF;
  4920. for (i = 0; i < 8; i++)
  4921. if (bits & (0x1<<i))
  4922. {
  4923. snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
  4924. t += strlen(t);
  4925. }
  4926. snprintf(t, BUFFER_SIZE(pbuffer, t), ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
  4927. }
  4928. break;
  4929. case CMD_ROPERPARAM:
  4930. snprintf(t, BUFFER_SIZE(pbuffer, t), "%2x %.1f %.1f %.1f %.1f",
  4931. mb(0), getflt((unsigned char *)&mb(1)), getflt((unsigned char *)&mb(5)),
  4932. getflt((unsigned char *)&mb(9)), getflt((unsigned char *)&mb(13)));
  4933. break;
  4934. case CMD_RUTCPARAM:
  4935. {
  4936. float t0t = getflt((unsigned char *)&mb(14));
  4937. short wnt = getshort((unsigned char *)&mb(18));
  4938. short dtls = getshort((unsigned char *)&mb(12));
  4939. short wnlsf = getshort((unsigned char *)&mb(20));
  4940. short dn = getshort((unsigned char *)&mb(22));
  4941. short dtlsf = getshort((unsigned char *)&mb(24));
  4942. if ((int)t0t != 0)
  4943. {
  4944. mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf, BUFFER_SIZE(pbuffer, t));
  4945. }
  4946. else
  4947. {
  4948. strncpy(t, "<NO UTC DATA>", BUFFER_SIZE(pbuffer, t));
  4949. }
  4950. }
  4951. break;
  4952. case CMD_RSAT1BIAS:
  4953. snprintf(t, BUFFER_SIZE(pbuffer, t), "%.1fm %.2fm/s at %.1fs",
  4954. getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8)));
  4955. break;
  4956. case CMD_RIOOPTIONS:
  4957. {
  4958. snprintf(t, BUFFER_SIZE(pbuffer, t), "%02x %02x %02x %02x",
  4959. mb(0), mb(1), mb(2), mb(3));
  4960. if (mb(0) != TRIM_POS_OPT ||
  4961. mb(2) != TRIM_TIME_OPT)
  4962. {
  4963. (void)trimbletsip_setup(parse, "bad io options");
  4964. }
  4965. }
  4966. break;
  4967. case CMD_RSPOSXYZ:
  4968. {
  4969. double x = getflt((unsigned char *)&mb(0));
  4970. double y = getflt((unsigned char *)&mb(4));
  4971. double z = getflt((unsigned char *)&mb(8));
  4972. double f = getflt((unsigned char *)&mb(12));
  4973. if (f > 0.0)
  4974. snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
  4975. x, y, z,
  4976. f);
  4977. else
  4978. return;
  4979. }
  4980. break;
  4981. case CMD_RSLLAPOS:
  4982. {
  4983. double lat = getflt((unsigned char *)&mb(0));
  4984. double lng = getflt((unsigned char *)&mb(4));
  4985. double f = getflt((unsigned char *)&mb(12));
  4986. if (f > 0.0)
  4987. snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, long %f %c, alt %.2fm",
  4988. ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
  4989. ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
  4990. getflt((unsigned char *)&mb(8)));
  4991. else
  4992. return;
  4993. }
  4994. break;
  4995. case CMD_RDOUBLEXYZ:
  4996. {
  4997. double x = getdbl((unsigned char *)&mb(0));
  4998. double y = getdbl((unsigned char *)&mb(8));
  4999. double z = getdbl((unsigned char *)&mb(16));
  5000. snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm",
  5001. x, y, z);
  5002. }
  5003. break;
  5004. case CMD_RDOUBLELLA:
  5005. {
  5006. double lat = getdbl((unsigned char *)&mb(0));
  5007. double lng = getdbl((unsigned char *)&mb(8));
  5008. snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, lon %f %c, alt %.2fm",
  5009. ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
  5010. ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
  5011. getdbl((unsigned char *)&mb(16)));
  5012. }
  5013. break;
  5014. case CMD_RALLINVIEW:
  5015. {
  5016. int i, sats;
  5017. strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
  5018. t += strlen(t);
  5019. switch (mb(0) & 0x7)
  5020. {
  5021. default:
  5022. snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
  5023. break;
  5024. case 3:
  5025. strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
  5026. break;
  5027. case 4:
  5028. strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
  5029. break;
  5030. }
  5031. t += strlen(t);
  5032. if (mb(0) & 0x8)
  5033. strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
  5034. else
  5035. strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
  5036. t += strlen(t);
  5037. sats = (mb(0)>>4) & 0xF;
  5038. snprintf(t, BUFFER_SIZE(pbuffer, t), "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
  5039. getflt((unsigned char *)&mb(1)),
  5040. getflt((unsigned char *)&mb(5)),
  5041. getflt((unsigned char *)&mb(9)),
  5042. getflt((unsigned char *)&mb(13)),
  5043. sats, (sats == 1) ? "" : "s");
  5044. t += strlen(t);
  5045. for (i=0; i < sats; i++)
  5046. {
  5047. snprintf(t, BUFFER_SIZE(pbuffer, t), "%s%02d", i ? ", " : "", mb(17+i));
  5048. t += strlen(t);
  5049. if (tr)
  5050. tr->ctrack |= (1 << (mb(17+i)-1));
  5051. }
  5052. if (tr)
  5053. { /* mark for tracking status query */
  5054. tr->qtracking = 1;
  5055. }
  5056. }
  5057. break;
  5058. case CMD_RSTATTRACK:
  5059. {
  5060. snprintf(t-2, BUFFER_SIZE(pbuffer, t-2), "[%02d]=\"", mb(0)); /* add index to var name */
  5061. t += strlen(t);
  5062. if (getflt((unsigned char *)&mb(4)) < 0.0)
  5063. {
  5064. strncpy(t, "<NO MEASUREMENTS>", BUFFER_SIZE(pbuffer, t));
  5065. var_flag &= ~DEF;
  5066. }
  5067. else
  5068. {
  5069. snprintf(t, BUFFER_SIZE(pbuffer, t), "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
  5070. (mb(1) & 0xFF)>>3,
  5071. mb(2) ? ((mb(2) == 1) ? "ACQ" : "SRCH") : "NEVER",
  5072. mb(3),
  5073. getflt((unsigned char *)&mb(4)),
  5074. getflt((unsigned char *)&mb(12)) * RTOD,
  5075. getflt((unsigned char *)&mb(16)) * RTOD);
  5076. t += strlen(t);
  5077. if (mb(20))
  5078. {
  5079. var_flag &= ~DEF;
  5080. strncpy(t, ", OLD", BUFFER_SIZE(pbuffer, t));
  5081. }
  5082. t += strlen(t);
  5083. if (mb(22))
  5084. {
  5085. if (mb(22) == 1)
  5086. strncpy(t, ", BAD PARITY", BUFFER_SIZE(pbuffer, t));
  5087. else
  5088. if (mb(22) == 2)
  5089. strncpy(t, ", BAD EPH HEALTH", BUFFER_SIZE(pbuffer, t));
  5090. }
  5091. t += strlen(t);
  5092. if (mb(23))
  5093. strncpy(t, ", collecting data", BUFFER_SIZE(pbuffer, t));
  5094. }
  5095. }
  5096. break;
  5097. default:
  5098. strncpy(t, "<UNDECODED>", BUFFER_SIZE(pbuffer, t));
  5099. break;
  5100. }
  5101. t += strlen(t);
  5102. strncpy(t,"\"", BUFFER_SIZE(pbuffer, t));
  5103. set_var(&parse->kv, pbuffer, sizeof(pbuffer), var_flag);
  5104. }
  5105. }
  5106. /**============================================================
  5107. ** RAWDCF support
  5108. **/
  5109. /*--------------------------------------------------
  5110. * rawdcf_init_1 - set up modem lines for RAWDCF receivers
  5111. * SET DTR line
  5112. */
  5113. #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
  5114. static int
  5115. rawdcf_init_1(
  5116. struct parseunit *parse
  5117. )
  5118. {
  5119. /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
  5120. /*
  5121. * You can use the RS232 to supply the power for a DCF77 receiver.
  5122. * Here a voltage between the DTR and the RTS line is used. Unfortunately
  5123. * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
  5124. */
  5125. int sl232;
  5126. if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
  5127. {
  5128. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
  5129. return 0;
  5130. }
  5131. #ifdef TIOCM_DTR
  5132. sl232 = (sl232 & ~TIOCM_RTS) | TIOCM_DTR; /* turn on DTR, clear RTS for power supply */
  5133. #else
  5134. sl232 = (sl232 & ~CIOCM_RTS) | CIOCM_DTR; /* turn on DTR, clear RTS for power supply */
  5135. #endif
  5136. if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
  5137. {
  5138. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
  5139. }
  5140. return 0;
  5141. }
  5142. #else
  5143. static int
  5144. rawdcfdtr_init_1(
  5145. struct parseunit *parse
  5146. )
  5147. {
  5148. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer));
  5149. return 0;
  5150. }
  5151. #endif /* DTR initialisation type */
  5152. /*--------------------------------------------------
  5153. * rawdcf_init_2 - set up modem lines for RAWDCF receivers
  5154. * CLR DTR line, SET RTS line
  5155. */
  5156. #if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS))
  5157. static int
  5158. rawdcf_init_2(
  5159. struct parseunit *parse
  5160. )
  5161. {
  5162. /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
  5163. /*
  5164. * You can use the RS232 to supply the power for a DCF77 receiver.
  5165. * Here a voltage between the DTR and the RTS line is used. Unfortunately
  5166. * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
  5167. */
  5168. int sl232;
  5169. if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
  5170. {
  5171. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
  5172. return 0;
  5173. }
  5174. #ifdef TIOCM_RTS
  5175. sl232 = (sl232 & ~TIOCM_DTR) | TIOCM_RTS; /* turn on RTS, clear DTR for power supply */
  5176. #else
  5177. sl232 = (sl232 & ~CIOCM_DTR) | CIOCM_RTS; /* turn on RTS, clear DTR for power supply */
  5178. #endif
  5179. if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
  5180. {
  5181. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
  5182. }
  5183. return 0;
  5184. }
  5185. #else
  5186. static int
  5187. rawdcf_init_2(
  5188. struct parseunit *parse
  5189. )
  5190. {
  5191. msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer));
  5192. return 0;
  5193. }
  5194. #endif /* DTR initialisation type */
  5195. #else /* defined(REFCLOCK) && defined(PARSE) */
  5196. int refclock_parse_bs;
  5197. #endif /* defined(REFCLOCK) && defined(PARSE) */
  5198. /*
  5199. * History:
  5200. *
  5201. * refclock_parse.c,v
  5202. * Revision 4.81 2009/05/01 10:15:29 kardel
  5203. * use new refclock_ppsapi interface
  5204. *
  5205. * Revision 4.80 2007/08/11 12:06:29 kardel
  5206. * update comments wrt/ to PPS
  5207. *
  5208. * Revision 4.79 2007/08/11 11:52:23 kardel
  5209. * - terminate io bindings before io_closeclock() will close our file descriptor
  5210. *
  5211. * Revision 4.78 2006/12/22 20:08:27 kardel
  5212. * Bug 746 (RFE): add configuration for Expert mouseCLOCK USB v2.0 as mode 19
  5213. *
  5214. * Revision 4.77 2006/08/05 07:44:49 kardel
  5215. * support optionally separate PPS devices via /dev/refclockpps-{0..3}
  5216. *
  5217. * Revision 4.76 2006/06/22 18:40:47 kardel
  5218. * clean up signedness (gcc 4)
  5219. *
  5220. * Revision 4.75 2006/06/22 16:58:10 kardel
  5221. * Bug #632: call parse_ppsapi() in parse_ctl() when updating
  5222. * the PPS offset. Fix sign of offset passed to kernel.
  5223. *
  5224. * Revision 4.74 2006/06/18 21:18:37 kardel
  5225. * NetBSD Coverity CID 3796: possible NULL deref
  5226. *
  5227. * Revision 4.73 2006/05/26 14:23:46 kardel
  5228. * cleanup of copyright info
  5229. *
  5230. * Revision 4.72 2006/05/26 14:19:43 kardel
  5231. * cleanup of ioctl cruft
  5232. *
  5233. * Revision 4.71 2006/05/26 14:15:57 kardel
  5234. * delay adding refclock to async refclock io after all initializations
  5235. *
  5236. * Revision 4.70 2006/05/25 18:20:50 kardel
  5237. * bug #619
  5238. * terminate parse io engine after de-registering
  5239. * from refclock io engine
  5240. *
  5241. * Revision 4.69 2006/05/25 17:28:02 kardel
  5242. * complete refclock io structure initialization *before* inserting it into the
  5243. * refclock input machine (avoids null pointer deref) (bug #619)
  5244. *
  5245. * Revision 4.68 2006/05/01 17:02:51 kardel
  5246. * copy receiver method also for newlwy created receive buffers
  5247. *
  5248. * Revision 4.67 2006/05/01 14:37:29 kardel
  5249. * If an input buffer parses into more than one message do insert the
  5250. * parsed message in a new input buffer instead of processing it
  5251. * directly. This avoids deed complicated processing in signal
  5252. * handling.
  5253. *
  5254. * Revision 4.66 2006/03/18 00:45:30 kardel
  5255. * coverity fixes found in NetBSD coverity scan
  5256. *
  5257. * Revision 4.65 2006/01/26 06:08:33 kardel
  5258. * output errno on PPS setup failure
  5259. *
  5260. * Revision 4.64 2005/11/09 20:44:47 kardel
  5261. * utilize full PPS timestamp resolution from PPS API
  5262. *
  5263. * Revision 4.63 2005/10/07 22:10:25 kardel
  5264. * bounded buffer implementation
  5265. *
  5266. * Revision 4.62.2.2 2005/09/25 10:20:16 kardel
  5267. * avoid unexpected buffer overflows due to sprintf("%f") on strange floats:
  5268. * replace almost all str* and *printf functions be their buffer bounded
  5269. * counterparts
  5270. *
  5271. * Revision 4.62.2.1 2005/08/27 16:19:27 kardel
  5272. * limit re-set rate of trimble clocks
  5273. *
  5274. * Revision 4.62 2005/08/06 17:40:00 kardel
  5275. * cleanup size handling wrt/ to buffer boundaries
  5276. *
  5277. * Revision 4.61 2005/07/27 21:16:19 kardel
  5278. * fix a long (> 11 years) misconfiguration wrt/ Meinberg cflag factory
  5279. * default setup. CSTOPB was missing for the 7E2 default data format of
  5280. * the DCF77 clocks.
  5281. *
  5282. * Revision 4.60 2005/07/17 21:14:44 kardel
  5283. * change contents of version string to include the RCS/CVS Id
  5284. *
  5285. * Revision 4.59 2005/07/06 06:56:38 kardel
  5286. * syntax error
  5287. *
  5288. * Revision 4.58 2005/07/04 13:10:40 kardel
  5289. * fix bug 455: tripping over NULL pointer on cleanup
  5290. * fix shadow storage logic for ppsphaseadjust and trustime wrt/ time2
  5291. * fix compiler warnings for some platforms wrt/ printf formatstrings and
  5292. * varying structure element sizes
  5293. * reorder assignment in binding to avoid tripping over NULL pointers
  5294. *
  5295. * Revision 4.57 2005/06/25 09:25:19 kardel
  5296. * sort out log output sequence
  5297. *
  5298. * Revision 4.56 2005/06/14 21:47:27 kardel
  5299. * collect samples only if samples are ok (sync or trusted flywheel)
  5300. * propagate pps phase adjustment value to kernel via PPSAPI to help HARDPPS
  5301. * en- and dis-able HARDPPS in correlation to receiver sync state
  5302. *
  5303. * Revision 4.55 2005/06/02 21:28:31 kardel
  5304. * clarify trust logic
  5305. *
  5306. * Revision 4.54 2005/06/02 17:06:49 kardel
  5307. * change status reporting to use fixed refclock_report()
  5308. *
  5309. * Revision 4.53 2005/06/02 16:33:31 kardel
  5310. * fix acceptance of clocks unsync clocks right at start
  5311. *
  5312. * Revision 4.52 2005/05/26 21:55:06 kardel
  5313. * cleanup status reporting
  5314. *
  5315. * Revision 4.51 2005/05/26 19:19:14 kardel
  5316. * implement fast refclock startup
  5317. *
  5318. * Revision 4.50 2005/04/16 20:51:35 kardel
  5319. * set pps_enable = 1 when binding a kernel PPS source
  5320. *
  5321. * Revision 4.49 2005/04/16 17:29:26 kardel
  5322. * add non polling clock type 18 for just listenning to Meinberg clocks
  5323. *
  5324. * Revision 4.48 2005/04/16 16:22:27 kardel
  5325. * bk sync 20050415 ntp-dev
  5326. *
  5327. * Revision 4.47 2004/11/29 10:42:48 kardel
  5328. * bk sync ntp-dev 20041129
  5329. *
  5330. * Revision 4.46 2004/11/29 10:26:29 kardel
  5331. * keep fudgetime2 in sync with trusttime/ppsphaseadjust depending in flag1
  5332. *
  5333. * Revision 4.45 2004/11/14 20:53:20 kardel
  5334. * clear PPS flags after using them
  5335. *
  5336. * Revision 4.44 2004/11/14 15:29:41 kardel
  5337. * support PPSAPI, upgrade Copyright to Berkeley style
  5338. *
  5339. * Revision 4.43 2001/05/26 22:53:16 kardel
  5340. * 20010526 reconcilation
  5341. *
  5342. * Revision 4.42 2000/05/14 15:31:51 kardel
  5343. * PPSAPI && RAWDCF modemline support
  5344. *
  5345. * Revision 4.41 2000/04/09 19:50:45 kardel
  5346. * fixed rawdcfdtr_init() -> rawdcf_init_1
  5347. *
  5348. * Revision 4.40 2000/04/09 15:27:55 kardel
  5349. * modem line fiddle in rawdcf_init_2
  5350. *
  5351. * Revision 4.39 2000/03/18 09:16:55 kardel
  5352. * PPSAPI integration
  5353. *
  5354. * Revision 4.38 2000/03/05 20:25:06 kardel
  5355. * support PPSAPI
  5356. *
  5357. * Revision 4.37 2000/03/05 20:11:14 kardel
  5358. * 4.0.99g reconcilation
  5359. *
  5360. * Revision 4.36 1999/11/28 17:18:20 kardel
  5361. * disabled burst mode
  5362. *
  5363. * Revision 4.35 1999/11/28 09:14:14 kardel
  5364. * RECON_4_0_98F
  5365. *
  5366. * Revision 4.34 1999/05/14 06:08:05 kardel
  5367. * store current_time in a suitable container (u_long)
  5368. *
  5369. * Revision 4.33 1999/05/13 21:48:38 kardel
  5370. * double the no response timeout interval
  5371. *
  5372. * Revision 4.32 1999/05/13 20:09:13 kardel
  5373. * complain only about missing polls after a full poll interval
  5374. *
  5375. * Revision 4.31 1999/05/13 19:59:32 kardel
  5376. * add clock type 16 for RTS set DTR clr in RAWDCF
  5377. *
  5378. * Revision 4.30 1999/02/28 20:36:43 kardel
  5379. * fixed printf fmt
  5380. *
  5381. * Revision 4.29 1999/02/28 19:58:23 kardel
  5382. * updated copyright information
  5383. *
  5384. * Revision 4.28 1999/02/28 19:01:50 kardel
  5385. * improved debug out on sent Meinberg messages
  5386. *
  5387. * Revision 4.27 1999/02/28 18:05:55 kardel
  5388. * no linux/ppsclock.h stuff
  5389. *
  5390. * Revision 4.26 1999/02/28 15:27:27 kardel
  5391. * wharton clock integration
  5392. *
  5393. * Revision 4.25 1999/02/28 14:04:46 kardel
  5394. * added missing double quotes to UTC information string
  5395. *
  5396. * Revision 4.24 1999/02/28 12:06:50 kardel
  5397. * (parse_control): using gmprettydate instead of prettydate()
  5398. * (mk_utcinfo): new function for formatting GPS derived UTC information
  5399. * (gps16x_message): changed to use mk_utcinfo()
  5400. * (trimbletsip_message): changed to use mk_utcinfo()
  5401. * ignoring position information in unsynchronized mode
  5402. * (parse_start): augument linux support for optional ASYNC_LOW_LATENCY
  5403. *
  5404. * Revision 4.23 1999/02/23 19:47:53 kardel
  5405. * fixed #endifs
  5406. * (stream_receive): fixed formats
  5407. *
  5408. * Revision 4.22 1999/02/22 06:21:02 kardel
  5409. * use new autoconfig symbols
  5410. *
  5411. * Revision 4.21 1999/02/21 12:18:13 kardel
  5412. * 4.91f reconcilation
  5413. *
  5414. * Revision 4.20 1999/02/21 10:53:36 kardel
  5415. * initial Linux PPSkit version
  5416. *
  5417. * Revision 4.19 1999/02/07 09:10:45 kardel
  5418. * clarify STREAMS mitigation rules in comment
  5419. *
  5420. * Revision 4.18 1998/12/20 23:45:34 kardel
  5421. * fix types and warnings
  5422. *
  5423. * Revision 4.17 1998/11/15 21:24:51 kardel
  5424. * cannot access mbg_ routines when CLOCK_MEINBERG
  5425. * is not defined
  5426. *
  5427. * Revision 4.16 1998/11/15 20:28:17 kardel
  5428. * Release 4.0.73e13 reconcilation
  5429. *
  5430. * Revision 4.15 1998/08/22 21:56:08 kardel
  5431. * fixed IO handling for non-STREAM IO
  5432. *
  5433. * Revision 4.14 1998/08/16 19:00:48 kardel
  5434. * (gps16x_message): reduced UTC parameter information (dropped A0,A1)
  5435. * made uval a local variable (killed one of the last globals)
  5436. * (sendetx): added logging of messages when in debug mode
  5437. * (trimble_check): added periodic checks to facilitate re-initialization
  5438. * (trimbletsip_init): made use of EOL character if in non-kernel operation
  5439. * (trimbletsip_message): extended message interpretation
  5440. * (getdbl): fixed data conversion
  5441. *
  5442. * Revision 4.13 1998/08/09 22:29:13 kardel
  5443. * Trimble TSIP support
  5444. *
  5445. * Revision 4.12 1998/07/11 10:05:34 kardel
  5446. * Release 4.0.73d reconcilation
  5447. *
  5448. * Revision 4.11 1998/06/14 21:09:42 kardel
  5449. * Sun acc cleanup
  5450. *
  5451. * Revision 4.10 1998/06/13 12:36:45 kardel
  5452. * signed/unsigned, name clashes
  5453. *
  5454. * Revision 4.9 1998/06/12 15:30:00 kardel
  5455. * prototype fixes
  5456. *
  5457. * Revision 4.8 1998/06/12 11:19:42 kardel
  5458. * added direct input processing routine for refclocks in
  5459. * order to avaiod that single character io gobbles up all
  5460. * receive buffers and drops input data. (Problem started
  5461. * with fast machines so a character a buffer was possible
  5462. * one of the few cases where faster machines break existing
  5463. * allocation algorithms)
  5464. *
  5465. * Revision 4.7 1998/06/06 18:35:20 kardel
  5466. * (parse_start): added BURST mode initialisation
  5467. *
  5468. * Revision 4.6 1998/05/27 06:12:46 kardel
  5469. * RAWDCF_BASEDELAY default added
  5470. * old comment removed
  5471. * casts for ioctl()
  5472. *
  5473. * Revision 4.5 1998/05/25 22:05:09 kardel
  5474. * RAWDCF_SETDTR option removed
  5475. * clock type 14 attempts to set DTR for
  5476. * power supply of RAWDCF receivers
  5477. *
  5478. * Revision 4.4 1998/05/24 16:20:47 kardel
  5479. * updated comments referencing Meinberg clocks
  5480. * added RAWDCF clock with DTR set option as type 14
  5481. *
  5482. * Revision 4.3 1998/05/24 10:48:33 kardel
  5483. * calibrated CONRAD RAWDCF default fudge factor
  5484. *
  5485. * Revision 4.2 1998/05/24 09:59:35 kardel
  5486. * corrected version information (ntpq support)
  5487. *
  5488. * Revision 4.1 1998/05/24 09:52:31 kardel
  5489. * use fixed format only (new IO model)
  5490. * output debug to stdout instead of msyslog()
  5491. * don't include >"< in ASCII output in order not to confuse
  5492. * ntpq parsing
  5493. *
  5494. * Revision 4.0 1998/04/10 19:52:11 kardel
  5495. * Start 4.0 release version numbering
  5496. *
  5497. * Revision 1.2 1998/04/10 19:28:04 kardel
  5498. * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
  5499. * derived from 3.105.1.2 from V3 tree
  5500. *
  5501. * Revision information 3.1 - 3.105 from log deleted 1998/04/10 kardel
  5502. *
  5503. */