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