1c0b746e5SOllivier Robert /* 2ea906c41SOllivier Robert * /src/NTP/REPOSITORY/ntp4-dev/libparse/clk_meinberg.c,v 4.12.2.1 2005/09/25 10:22:35 kardel RELEASE_20050925_A 3c0b746e5SOllivier Robert * 4ea906c41SOllivier Robert * clk_meinberg.c,v 4.12.2.1 2005/09/25 10:22:35 kardel RELEASE_20050925_A 5c0b746e5SOllivier Robert * 6c0b746e5SOllivier Robert * Meinberg clock support 7c0b746e5SOllivier Robert * 8276da39aSCy Schubert * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org> 9a25439b6SCy Schubert * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 10c0b746e5SOllivier Robert * 11ea906c41SOllivier Robert * Redistribution and use in source and binary forms, with or without 12ea906c41SOllivier Robert * modification, are permitted provided that the following conditions 13ea906c41SOllivier Robert * are met: 14ea906c41SOllivier Robert * 1. Redistributions of source code must retain the above copyright 15ea906c41SOllivier Robert * notice, this list of conditions and the following disclaimer. 16ea906c41SOllivier Robert * 2. Redistributions in binary form must reproduce the above copyright 17ea906c41SOllivier Robert * notice, this list of conditions and the following disclaimer in the 18ea906c41SOllivier Robert * documentation and/or other materials provided with the distribution. 19ea906c41SOllivier Robert * 3. Neither the name of the author nor the names of its contributors 20ea906c41SOllivier Robert * may be used to endorse or promote products derived from this software 21ea906c41SOllivier Robert * without specific prior written permission. 22ea906c41SOllivier Robert * 23ea906c41SOllivier Robert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24ea906c41SOllivier Robert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25ea906c41SOllivier Robert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26ea906c41SOllivier Robert * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27ea906c41SOllivier Robert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28ea906c41SOllivier Robert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29ea906c41SOllivier Robert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30ea906c41SOllivier Robert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31ea906c41SOllivier Robert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32ea906c41SOllivier Robert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33ea906c41SOllivier Robert * SUCH DAMAGE. 34c0b746e5SOllivier Robert * 35c0b746e5SOllivier Robert */ 36c0b746e5SOllivier Robert 37c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 38c0b746e5SOllivier Robert # include <config.h> 39c0b746e5SOllivier Robert #endif 40c0b746e5SOllivier Robert 41c0b746e5SOllivier Robert #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_MEINBERG) 42c0b746e5SOllivier Robert 43c0b746e5SOllivier Robert #include "ntp_fp.h" 44c0b746e5SOllivier Robert #include "ntp_unixtime.h" 45c0b746e5SOllivier Robert #include "ntp_calendar.h" 46c0b746e5SOllivier Robert 47c0b746e5SOllivier Robert #include "ntp_machine.h" 48c0b746e5SOllivier Robert 49c0b746e5SOllivier Robert #include "parse.h" 50c0b746e5SOllivier Robert 51c0b746e5SOllivier Robert #ifndef PARSESTREAM 52c0b746e5SOllivier Robert #include <stdio.h> 53c0b746e5SOllivier Robert #else 54c0b746e5SOllivier Robert #include "sys/parsestreams.h" 55c0b746e5SOllivier Robert #endif 56c0b746e5SOllivier Robert 57c0b746e5SOllivier Robert #include "ntp_stdlib.h" 58c0b746e5SOllivier Robert 59c0b746e5SOllivier Robert #include "ntp_stdlib.h" 60c0b746e5SOllivier Robert 61c0b746e5SOllivier Robert #include "mbg_gps166.h" 62c0b746e5SOllivier Robert #include "binio.h" 63c0b746e5SOllivier Robert #include "ascii.h" 64c0b746e5SOllivier Robert 65c0b746e5SOllivier Robert /* 66c0b746e5SOllivier Robert * The Meinberg receiver every second sends a datagram of the following form 67c0b746e5SOllivier Robert * (Standard Format) 68c0b746e5SOllivier Robert * 69c0b746e5SOllivier Robert * <STX>D:<dd>.<mm>.<yy>;T:<w>;U:<hh>:<mm>:<ss>;<S><F><D><A><ETX> 70c0b746e5SOllivier Robert * pos: 0 00 00 0 00 0 11 111 1 111 12 2 22 2 22 2 2 2 3 3 3 71c0b746e5SOllivier Robert * 1 23 45 6 78 9 01 234 5 678 90 1 23 4 56 7 8 9 0 1 2 72c0b746e5SOllivier Robert * <STX> = '\002' ASCII start of text 73c0b746e5SOllivier Robert * <ETX> = '\003' ASCII end of text 74c0b746e5SOllivier Robert * <dd>,<mm>,<yy> = day, month, year(2 digits!!) 75c0b746e5SOllivier Robert * <w> = day of week (sunday= 0) 76c0b746e5SOllivier Robert * <hh>,<mm>,<ss> = hour, minute, second 77c0b746e5SOllivier Robert * <S> = '#' if never synced since powerup for DCF C51 78c0b746e5SOllivier Robert * = '#' if not PZF sychronisation available for PZF 535/509 79c0b746e5SOllivier Robert * = ' ' if ok 80c0b746e5SOllivier Robert * <F> = '*' if time comes from internal quartz 81c0b746e5SOllivier Robert * = ' ' if completely synched 82c0b746e5SOllivier Robert * <D> = 'S' if daylight saving time is active 83c0b746e5SOllivier Robert * = 'U' if time is represented in UTC 84c0b746e5SOllivier Robert * = ' ' if no special condition exists 85c0b746e5SOllivier Robert * <A> = '!' during the hour preceeding an daylight saving time 86c0b746e5SOllivier Robert * start/end change 87c0b746e5SOllivier Robert * = 'A' leap second insert warning 88c0b746e5SOllivier Robert * = ' ' if no special condition exists 89c0b746e5SOllivier Robert * 90c0b746e5SOllivier Robert * Extended data format (PZFUERL for PZF type clocks) 91c0b746e5SOllivier Robert * 92c0b746e5SOllivier Robert * <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <U><S><F><D><A><L><R><ETX> 93c0b746e5SOllivier Robert * pos: 0 00 0 00 0 00 11 1 11 11 1 11 2 22 22 2 2 2 2 2 3 3 3 94c0b746e5SOllivier Robert * 1 23 4 56 7 89 01 2 34 56 7 89 0 12 34 5 6 7 8 9 0 1 2 95c0b746e5SOllivier Robert * <STX> = '\002' ASCII start of text 96c0b746e5SOllivier Robert * <ETX> = '\003' ASCII end of text 97c0b746e5SOllivier Robert * <dd>,<mm>,<yy> = day, month, year(2 digits!!) 98c0b746e5SOllivier Robert * <w> = day of week (sunday= 0) 99c0b746e5SOllivier Robert * <hh>,<mm>,<ss> = hour, minute, second 100c0b746e5SOllivier Robert * <U> = 'U' UTC time display 101c0b746e5SOllivier Robert * <S> = '#' if never synced since powerup else ' ' for DCF C51 102c0b746e5SOllivier Robert * '#' if not PZF sychronisation available else ' ' for PZF 535/509 103c0b746e5SOllivier Robert * <F> = '*' if time comes from internal quartz else ' ' 104c0b746e5SOllivier Robert * <D> = 'S' if daylight saving time is active else ' ' 105c0b746e5SOllivier Robert * <A> = '!' during the hour preceeding an daylight saving time 106c0b746e5SOllivier Robert * start/end change 107c0b746e5SOllivier Robert * <L> = 'A' LEAP second announcement 108a25439b6SCy Schubert * <R> = 'R' "call bit" used to signalize irregularities in the control facilities, 109a25439b6SCy Schubert * usually ' ', until 2003 indicated transmission via alternate antenna 110c0b746e5SOllivier Robert * 111a25439b6SCy Schubert * Meinberg GPS receivers 112c0b746e5SOllivier Robert * 113a25439b6SCy Schubert * For very old devices you must get the Uni-Erlangen firmware for the GPS receiver support 114c0b746e5SOllivier Robert * to work to full satisfaction ! 115a25439b6SCy Schubert * With newer GPS receiver types the Uni Erlangen string format can be configured at the device. 116c0b746e5SOllivier Robert * 117c0b746e5SOllivier Robert * <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <+/-><00:00>; <U><S><F><D><A><L><R><L>; <position...><ETX> 118c0b746e5SOllivier Robert * 119c0b746e5SOllivier Robert * 000000000111111111122222222223333333333444444444455555555556666666 120c0b746e5SOllivier Robert * 123456789012345678901234567890123456789012345678901234567890123456 121c0b746e5SOllivier Robert * \x0209.07.93; 5; 08:48:26; +00:00; #*S!A L; 49.5736N 11.0280E 373m\x03 122c0b746e5SOllivier Robert * 123c0b746e5SOllivier Robert * 124c0b746e5SOllivier Robert * <STX> = '\002' ASCII start of text 125c0b746e5SOllivier Robert * <ETX> = '\003' ASCII end of text 126c0b746e5SOllivier Robert * <dd>,<mm>,<yy> = day, month, year(2 digits!!) 127c0b746e5SOllivier Robert * <w> = day of week (sunday= 0) 128c0b746e5SOllivier Robert * <hh>,<mm>,<ss> = hour, minute, second 129c0b746e5SOllivier Robert * <+/->,<00:00> = offset to UTC 130c0b746e5SOllivier Robert * <S> = '#' if never synced since powerup else ' ' 131c0b746e5SOllivier Robert * <F> = '*' if position is not confirmed else ' ' 132c0b746e5SOllivier Robert * <D> = 'S' if daylight saving time is active else ' ' 133c0b746e5SOllivier Robert * <A> = '!' during the hour preceeding an daylight saving time 134c0b746e5SOllivier Robert * start/end change 135c0b746e5SOllivier Robert * <L> = 'A' LEAP second announcement 136a25439b6SCy Schubert * <R> = 'R' "call bit" used to signalize irregularities in the control facilities, 137a25439b6SCy Schubert * usually ' ', until 2003 indicated transmission via alternate antenna 138a25439b6SCy Schubert * (reminiscent of PZF receivers) 139c0b746e5SOllivier Robert * <L> = 'L' on 23:59:60 140c0b746e5SOllivier Robert * 141c0b746e5SOllivier Robert * Binary messages have a lead in for a fixed header of SOH 142c0b746e5SOllivier Robert */ 143c0b746e5SOllivier Robert 144c0b746e5SOllivier Robert /*--------------------------------------------------------------*/ 145c0b746e5SOllivier Robert /* Name: csum() */ 146c0b746e5SOllivier Robert /* */ 147c0b746e5SOllivier Robert /* Purpose: Compute a checksum about a number of bytes */ 148c0b746e5SOllivier Robert /* */ 149c0b746e5SOllivier Robert /* Input: uchar *p address of the first byte */ 150c0b746e5SOllivier Robert /* short n the number of bytes */ 151c0b746e5SOllivier Robert /* */ 152c0b746e5SOllivier Robert /* Output: -- */ 153c0b746e5SOllivier Robert /* */ 154c0b746e5SOllivier Robert /* Ret val: the checksum */ 155c0b746e5SOllivier Robert /*+-------------------------------------------------------------*/ 156c0b746e5SOllivier Robert 157a25439b6SCy Schubert CSUM 158c0b746e5SOllivier Robert mbg_csum( 159c0b746e5SOllivier Robert unsigned char *p, 160c0b746e5SOllivier Robert unsigned int n 161c0b746e5SOllivier Robert ) 162c0b746e5SOllivier Robert { 163a25439b6SCy Schubert unsigned int sum = 0; 1642b15cb3dSCy Schubert unsigned int i; 165c0b746e5SOllivier Robert 166c0b746e5SOllivier Robert for ( i = 0; i < n; i++ ) 167c0b746e5SOllivier Robert sum += *p++; 168c0b746e5SOllivier Robert 169a25439b6SCy Schubert return (CSUM) sum; 170a25439b6SCy Schubert 171c0b746e5SOllivier Robert } /* csum */ 172c0b746e5SOllivier Robert 173c0b746e5SOllivier Robert void 174c0b746e5SOllivier Robert get_mbg_header( 175c0b746e5SOllivier Robert unsigned char **bufpp, 176c0b746e5SOllivier Robert GPS_MSG_HDR *headerp 177c0b746e5SOllivier Robert ) 178c0b746e5SOllivier Robert { 179a25439b6SCy Schubert headerp->cmd = (GPS_CMD) get_lsb_short(bufpp); 180a25439b6SCy Schubert headerp->len = get_lsb_uint16(bufpp); 181a25439b6SCy Schubert headerp->data_csum = (CSUM) get_lsb_short(bufpp); 182a25439b6SCy Schubert headerp->hdr_csum = (CSUM) get_lsb_short(bufpp); 183c0b746e5SOllivier Robert } 184c0b746e5SOllivier Robert 185c0b746e5SOllivier Robert static struct format meinberg_fmt[] = 186c0b746e5SOllivier Robert { 187c0b746e5SOllivier Robert { 188c0b746e5SOllivier Robert { 189c0b746e5SOllivier Robert { 3, 2}, { 6, 2}, { 9, 2}, 190c0b746e5SOllivier Robert { 18, 2}, { 21, 2}, { 24, 2}, 191c0b746e5SOllivier Robert { 14, 1}, { 27, 4}, { 29, 1}, 192c0b746e5SOllivier Robert }, 193c0b746e5SOllivier Robert (const unsigned char *)"\2D: . . ;T: ;U: . . ; \3", 194c0b746e5SOllivier Robert 0 195c0b746e5SOllivier Robert }, 196c0b746e5SOllivier Robert { /* special extended FAU Erlangen extended format */ 197c0b746e5SOllivier Robert { 198c0b746e5SOllivier Robert { 1, 2}, { 4, 2}, { 7, 2}, 199c0b746e5SOllivier Robert { 14, 2}, { 17, 2}, { 20, 2}, 200c0b746e5SOllivier Robert { 11, 1}, { 25, 4}, { 27, 1}, 201c0b746e5SOllivier Robert }, 202c0b746e5SOllivier Robert (const unsigned char *)"\2 . . ; ; : : ; \3", 203c0b746e5SOllivier Robert MBG_EXTENDED 204c0b746e5SOllivier Robert }, 205c0b746e5SOllivier Robert { /* special extended FAU Erlangen GPS format */ 206c0b746e5SOllivier Robert { 207c0b746e5SOllivier Robert { 1, 2}, { 4, 2}, { 7, 2}, 208c0b746e5SOllivier Robert { 14, 2}, { 17, 2}, { 20, 2}, 209c0b746e5SOllivier Robert { 11, 1}, { 32, 7}, { 35, 1}, 210c0b746e5SOllivier Robert { 25, 2}, { 28, 2}, { 24, 1} 211c0b746e5SOllivier Robert }, 212c0b746e5SOllivier Robert (const unsigned char *)"\2 . . ; ; : : ; : ; ; . . ", 213c0b746e5SOllivier Robert 0 214c0b746e5SOllivier Robert } 215c0b746e5SOllivier Robert }; 216c0b746e5SOllivier Robert 217a25439b6SCy Schubert static parse_cvt_fnc_t cvt_meinberg; 218a25439b6SCy Schubert static parse_cvt_fnc_t cvt_mgps; 219a25439b6SCy Schubert static parse_inp_fnc_t mbg_input; 220a25439b6SCy Schubert static parse_inp_fnc_t gps_input; 221c0b746e5SOllivier Robert 222c0b746e5SOllivier Robert struct msg_buf 223c0b746e5SOllivier Robert { 224c0b746e5SOllivier Robert unsigned short len; /* len to fill */ 225c0b746e5SOllivier Robert unsigned short phase; /* current input phase */ 226c0b746e5SOllivier Robert }; 227c0b746e5SOllivier Robert 228c0b746e5SOllivier Robert #define MBG_NONE 0 /* no data input */ 229c0b746e5SOllivier Robert #define MBG_HEADER 1 /* receiving header */ 230c0b746e5SOllivier Robert #define MBG_DATA 2 /* receiving data */ 231c0b746e5SOllivier Robert #define MBG_STRING 3 /* receiving standard data message */ 232c0b746e5SOllivier Robert 233c0b746e5SOllivier Robert clockformat_t clock_meinberg[] = 234c0b746e5SOllivier Robert { 235c0b746e5SOllivier Robert { 236c0b746e5SOllivier Robert mbg_input, /* normal input handling */ 237c0b746e5SOllivier Robert cvt_meinberg, /* Meinberg conversion */ 238c0b746e5SOllivier Robert pps_one, /* easy PPS monitoring */ 239c0b746e5SOllivier Robert 0, /* conversion configuration */ 240c0b746e5SOllivier Robert "Meinberg Standard", /* Meinberg simple format - beware */ 241c0b746e5SOllivier Robert 32, /* string buffer */ 242a25439b6SCy Schubert 0 /* no private data (complete packets) */ 243c0b746e5SOllivier Robert }, 244c0b746e5SOllivier Robert { 245c0b746e5SOllivier Robert mbg_input, /* normal input handling */ 246c0b746e5SOllivier Robert cvt_meinberg, /* Meinberg conversion */ 247c0b746e5SOllivier Robert pps_one, /* easy PPS monitoring */ 248c0b746e5SOllivier Robert 0, /* conversion configuration */ 249c0b746e5SOllivier Robert "Meinberg Extended", /* Meinberg enhanced format */ 250c0b746e5SOllivier Robert 32, /* string buffer */ 251a25439b6SCy Schubert 0 /* no private data (complete packets) */ 252c0b746e5SOllivier Robert }, 253c0b746e5SOllivier Robert { 254c0b746e5SOllivier Robert gps_input, /* no input handling */ 255a25439b6SCy Schubert cvt_mgps, /* Meinberg GPS receiver conversion */ 256c0b746e5SOllivier Robert pps_one, /* easy PPS monitoring */ 257c0b746e5SOllivier Robert (void *)&meinberg_fmt[2], /* conversion configuration */ 258c0b746e5SOllivier Robert "Meinberg GPS Extended", /* Meinberg FAU GPS format */ 259c0b746e5SOllivier Robert 512, /* string buffer */ 260a25439b6SCy Schubert sizeof(struct msg_buf) /* no private data (complete packets) */ 261c0b746e5SOllivier Robert } 262c0b746e5SOllivier Robert }; 263c0b746e5SOllivier Robert 264c0b746e5SOllivier Robert /* 265a25439b6SCy Schubert * parse_cvt_fnc_t cvt_meinberg 266c0b746e5SOllivier Robert * 267c0b746e5SOllivier Robert * convert simple type format 268c0b746e5SOllivier Robert */ 269c0b746e5SOllivier Robert static u_long 270c0b746e5SOllivier Robert cvt_meinberg( 271c0b746e5SOllivier Robert unsigned char *buffer, 272c0b746e5SOllivier Robert int size, 273c0b746e5SOllivier Robert struct format *unused, 274c0b746e5SOllivier Robert clocktime_t *clock_time, 275c0b746e5SOllivier Robert void *local 276c0b746e5SOllivier Robert ) 277c0b746e5SOllivier Robert { 278c0b746e5SOllivier Robert struct format *format; 279c0b746e5SOllivier Robert 280c0b746e5SOllivier Robert /* 281c0b746e5SOllivier Robert * select automagically correct data format 282c0b746e5SOllivier Robert */ 283c0b746e5SOllivier Robert if (Strok(buffer, meinberg_fmt[0].fixed_string)) 284c0b746e5SOllivier Robert { 285c0b746e5SOllivier Robert format = &meinberg_fmt[0]; 286c0b746e5SOllivier Robert } 287c0b746e5SOllivier Robert else 288c0b746e5SOllivier Robert { 289c0b746e5SOllivier Robert if (Strok(buffer, meinberg_fmt[1].fixed_string)) 290c0b746e5SOllivier Robert { 291c0b746e5SOllivier Robert format = &meinberg_fmt[1]; 292c0b746e5SOllivier Robert } 293c0b746e5SOllivier Robert else 294c0b746e5SOllivier Robert { 295c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 296c0b746e5SOllivier Robert } 297c0b746e5SOllivier Robert } 298c0b746e5SOllivier Robert 299c0b746e5SOllivier Robert /* 300c0b746e5SOllivier Robert * collect data 301c0b746e5SOllivier Robert */ 302c0b746e5SOllivier Robert if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, 303c0b746e5SOllivier Robert format->field_offsets[O_DAY].length) || 304c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, 305c0b746e5SOllivier Robert format->field_offsets[O_MONTH].length) || 306c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, 307c0b746e5SOllivier Robert format->field_offsets[O_YEAR].length) || 308c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, 309c0b746e5SOllivier Robert format->field_offsets[O_HOUR].length) || 310c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, 311c0b746e5SOllivier Robert format->field_offsets[O_MIN].length) || 312c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, 313c0b746e5SOllivier Robert format->field_offsets[O_SEC].length)) 314c0b746e5SOllivier Robert { 315c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 316c0b746e5SOllivier Robert } 317c0b746e5SOllivier Robert else 318c0b746e5SOllivier Robert { 319c0b746e5SOllivier Robert unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; 320c0b746e5SOllivier Robert 321c0b746e5SOllivier Robert clock_time->usecond = 0; 322c0b746e5SOllivier Robert clock_time->flags = PARSEB_S_LEAP; 323c0b746e5SOllivier Robert 324c0b746e5SOllivier Robert if (clock_time->second == 60) 325c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPSECOND; 326c0b746e5SOllivier Robert 327c0b746e5SOllivier Robert /* 328c0b746e5SOllivier Robert * in the extended timecode format we have also the 329c0b746e5SOllivier Robert * indication that the timecode is in UTC 330c0b746e5SOllivier Robert * for compatibilty reasons we start at the USUAL 331c0b746e5SOllivier Robert * offset (POWERUP flag) and know that the UTC indication 332c0b746e5SOllivier Robert * is the character before the powerup flag 333c0b746e5SOllivier Robert */ 334c0b746e5SOllivier Robert if ((format->flags & MBG_EXTENDED) && (f[-1] == 'U')) 335c0b746e5SOllivier Robert { 336c0b746e5SOllivier Robert /* 337c0b746e5SOllivier Robert * timecode is in UTC 338c0b746e5SOllivier Robert */ 339c0b746e5SOllivier Robert clock_time->utcoffset = 0; /* UTC */ 340c0b746e5SOllivier Robert clock_time->flags |= PARSEB_UTC; 341c0b746e5SOllivier Robert } 342c0b746e5SOllivier Robert else 343c0b746e5SOllivier Robert { 344c0b746e5SOllivier Robert /* 345c0b746e5SOllivier Robert * only calculate UTC offset if MET/MED is in time code 346c0b746e5SOllivier Robert * or we have the old time code format, where we do not 347c0b746e5SOllivier Robert * know whether it is UTC time or MET/MED 348c0b746e5SOllivier Robert * pray that nobody switches to UTC in the *old* standard time code 349c0b746e5SOllivier Robert * ROMS !!!! The new ROMS have 'U' at the ZONE field - good. 350c0b746e5SOllivier Robert */ 351c0b746e5SOllivier Robert switch (buffer[format->field_offsets[O_ZONE].offset]) 352c0b746e5SOllivier Robert { 353c0b746e5SOllivier Robert case ' ': 354c0b746e5SOllivier Robert clock_time->utcoffset = -1*60*60; /* MET */ 355c0b746e5SOllivier Robert break; 356c0b746e5SOllivier Robert 357c0b746e5SOllivier Robert case 'S': 358c0b746e5SOllivier Robert clock_time->utcoffset = -2*60*60; /* MED */ 359c0b746e5SOllivier Robert break; 360c0b746e5SOllivier Robert 361c0b746e5SOllivier Robert case 'U': 362c0b746e5SOllivier Robert /* 363c0b746e5SOllivier Robert * timecode is in UTC 364c0b746e5SOllivier Robert */ 365c0b746e5SOllivier Robert clock_time->utcoffset = 0; /* UTC */ 366c0b746e5SOllivier Robert clock_time->flags |= PARSEB_UTC; 367c0b746e5SOllivier Robert break; 368c0b746e5SOllivier Robert 369c0b746e5SOllivier Robert default: 370c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 371c0b746e5SOllivier Robert } 372c0b746e5SOllivier Robert } 373c0b746e5SOllivier Robert 374c0b746e5SOllivier Robert /* 375c0b746e5SOllivier Robert * gather status flags 376c0b746e5SOllivier Robert */ 377c0b746e5SOllivier Robert if (buffer[format->field_offsets[O_ZONE].offset] == 'S') 378c0b746e5SOllivier Robert clock_time->flags |= PARSEB_DST; 379c0b746e5SOllivier Robert 380c0b746e5SOllivier Robert if (f[0] == '#') 381c0b746e5SOllivier Robert clock_time->flags |= PARSEB_POWERUP; 382c0b746e5SOllivier Robert 383c0b746e5SOllivier Robert if (f[1] == '*') 384c0b746e5SOllivier Robert clock_time->flags |= PARSEB_NOSYNC; 385c0b746e5SOllivier Robert 386c0b746e5SOllivier Robert if (f[3] == '!') 387c0b746e5SOllivier Robert clock_time->flags |= PARSEB_ANNOUNCE; 388c0b746e5SOllivier Robert 389c0b746e5SOllivier Robert /* 390c0b746e5SOllivier Robert * oncoming leap second 391c0b746e5SOllivier Robert * 'a' code not confirmed - earth is not 392c0b746e5SOllivier Robert * expected to speed up 393c0b746e5SOllivier Robert */ 394c0b746e5SOllivier Robert if (f[3] == 'A') 395c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPADD; 396c0b746e5SOllivier Robert 397c0b746e5SOllivier Robert if (f[3] == 'a') 398c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPDEL; 399c0b746e5SOllivier Robert 400c0b746e5SOllivier Robert 401c0b746e5SOllivier Robert if (format->flags & MBG_EXTENDED) 402c0b746e5SOllivier Robert { 403276da39aSCy Schubert clock_time->flags |= PARSEB_S_CALLBIT; 404c0b746e5SOllivier Robert 405c0b746e5SOllivier Robert /* 406c0b746e5SOllivier Robert * DCF77 does not encode the direction - 407c0b746e5SOllivier Robert * so we take the current default - 408c0b746e5SOllivier Robert * earth slowing down 409c0b746e5SOllivier Robert */ 410c0b746e5SOllivier Robert clock_time->flags &= ~PARSEB_LEAPDEL; 411c0b746e5SOllivier Robert 412c0b746e5SOllivier Robert if (f[4] == 'A') 413c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPADD; 414c0b746e5SOllivier Robert 415c0b746e5SOllivier Robert if (f[5] == 'R') 416a25439b6SCy Schubert clock_time->flags |= PARSEB_CALLBIT; 417c0b746e5SOllivier Robert } 418c0b746e5SOllivier Robert return CVT_OK; 419c0b746e5SOllivier Robert } 420c0b746e5SOllivier Robert } 421c0b746e5SOllivier Robert 422c0b746e5SOllivier Robert 423c0b746e5SOllivier Robert /* 424a25439b6SCy Schubert * parse_inp_fnc_t mbg_input 425c0b746e5SOllivier Robert * 426a25439b6SCy Schubert * grab data from input stream 427c0b746e5SOllivier Robert */ 428c0b746e5SOllivier Robert static u_long 429c0b746e5SOllivier Robert mbg_input( 430c0b746e5SOllivier Robert parse_t *parseio, 431a25439b6SCy Schubert char ch, 432c0b746e5SOllivier Robert timestamp_t *tstamp 433c0b746e5SOllivier Robert ) 434c0b746e5SOllivier Robert { 435c0b746e5SOllivier Robert unsigned int rtc; 436c0b746e5SOllivier Robert 4373311ff84SXin LI parseprintf(DD_PARSE, ("mbg_input(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 438c0b746e5SOllivier Robert 439c0b746e5SOllivier Robert switch (ch) 440c0b746e5SOllivier Robert { 441c0b746e5SOllivier Robert case STX: 442c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("mbg_input: STX seen\n")); 443c0b746e5SOllivier Robert 444c0b746e5SOllivier Robert parseio->parse_index = 1; 445c0b746e5SOllivier Robert parseio->parse_data[0] = ch; 446c0b746e5SOllivier Robert parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ 447c0b746e5SOllivier Robert return PARSE_INP_SKIP; 448c0b746e5SOllivier Robert 449c0b746e5SOllivier Robert case ETX: 450c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("mbg_input: ETX seen\n")); 451c0b746e5SOllivier Robert if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) 452c0b746e5SOllivier Robert return parse_end(parseio); 453c0b746e5SOllivier Robert else 454c0b746e5SOllivier Robert return rtc; 455c0b746e5SOllivier Robert 456c0b746e5SOllivier Robert default: 457c0b746e5SOllivier Robert return parse_addchar(parseio, ch); 458c0b746e5SOllivier Robert } 459c0b746e5SOllivier Robert } 460c0b746e5SOllivier Robert 461c0b746e5SOllivier Robert 462c0b746e5SOllivier Robert /* 463a25439b6SCy Schubert * parse_cvt_fnc_t cvt_mgps 464c0b746e5SOllivier Robert * 465c0b746e5SOllivier Robert * convert Meinberg GPS format 466c0b746e5SOllivier Robert */ 467c0b746e5SOllivier Robert static u_long 468c0b746e5SOllivier Robert cvt_mgps( 469c0b746e5SOllivier Robert unsigned char *buffer, 470c0b746e5SOllivier Robert int size, 471c0b746e5SOllivier Robert struct format *format, 472c0b746e5SOllivier Robert clocktime_t *clock_time, 473c0b746e5SOllivier Robert void *local 474c0b746e5SOllivier Robert ) 475c0b746e5SOllivier Robert { 476c0b746e5SOllivier Robert if (!Strok(buffer, format->fixed_string)) 477c0b746e5SOllivier Robert { 478c0b746e5SOllivier Robert return cvt_meinberg(buffer, size, format, clock_time, local); 479c0b746e5SOllivier Robert } 480c0b746e5SOllivier Robert else 481c0b746e5SOllivier Robert { 482c0b746e5SOllivier Robert if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, 483c0b746e5SOllivier Robert format->field_offsets[O_DAY].length) || 484c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, 485c0b746e5SOllivier Robert format->field_offsets[O_MONTH].length) || 486c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, 487c0b746e5SOllivier Robert format->field_offsets[O_YEAR].length) || 488c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, 489c0b746e5SOllivier Robert format->field_offsets[O_HOUR].length) || 490c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, 491c0b746e5SOllivier Robert format->field_offsets[O_MIN].length) || 492c0b746e5SOllivier Robert Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, 493c0b746e5SOllivier Robert format->field_offsets[O_SEC].length)) 494c0b746e5SOllivier Robert { 495c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 496c0b746e5SOllivier Robert } 497c0b746e5SOllivier Robert else 498c0b746e5SOllivier Robert { 499c0b746e5SOllivier Robert long h; 500c0b746e5SOllivier Robert unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; 501c0b746e5SOllivier Robert 502c0b746e5SOllivier Robert clock_time->flags = PARSEB_S_LEAP|PARSEB_S_POSITION; 503c0b746e5SOllivier Robert 504c0b746e5SOllivier Robert clock_time->usecond = 0; 505c0b746e5SOllivier Robert 506c0b746e5SOllivier Robert /* 507c0b746e5SOllivier Robert * calculate UTC offset 508c0b746e5SOllivier Robert */ 509c0b746e5SOllivier Robert if (Stoi(&buffer[format->field_offsets[O_UTCHOFFSET].offset], &h, 510c0b746e5SOllivier Robert format->field_offsets[O_UTCHOFFSET].length)) 511c0b746e5SOllivier Robert { 512c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 513c0b746e5SOllivier Robert } 514c0b746e5SOllivier Robert else 515c0b746e5SOllivier Robert { 516c0b746e5SOllivier Robert if (Stoi(&buffer[format->field_offsets[O_UTCMOFFSET].offset], &clock_time->utcoffset, 517c0b746e5SOllivier Robert format->field_offsets[O_UTCMOFFSET].length)) 518c0b746e5SOllivier Robert { 519c0b746e5SOllivier Robert return CVT_FAIL|CVT_BADFMT; 520c0b746e5SOllivier Robert } 521c0b746e5SOllivier Robert 522c0b746e5SOllivier Robert clock_time->utcoffset += TIMES60(h); 523c0b746e5SOllivier Robert clock_time->utcoffset = TIMES60(clock_time->utcoffset); 524c0b746e5SOllivier Robert 525c0b746e5SOllivier Robert if (buffer[format->field_offsets[O_UTCSOFFSET].offset] != '-') 526c0b746e5SOllivier Robert { 527c0b746e5SOllivier Robert clock_time->utcoffset = -clock_time->utcoffset; 528c0b746e5SOllivier Robert } 529c0b746e5SOllivier Robert } 530c0b746e5SOllivier Robert 531c0b746e5SOllivier Robert /* 532c0b746e5SOllivier Robert * gather status flags 533c0b746e5SOllivier Robert */ 534c0b746e5SOllivier Robert if (buffer[format->field_offsets[O_ZONE].offset] == 'S') 535c0b746e5SOllivier Robert clock_time->flags |= PARSEB_DST; 536c0b746e5SOllivier Robert 537c0b746e5SOllivier Robert if (clock_time->utcoffset == 0) 538c0b746e5SOllivier Robert clock_time->flags |= PARSEB_UTC; 539c0b746e5SOllivier Robert 540c0b746e5SOllivier Robert /* 541c0b746e5SOllivier Robert * no sv's seen - no time & position 542c0b746e5SOllivier Robert */ 543c0b746e5SOllivier Robert if (f[0] == '#') 544c0b746e5SOllivier Robert clock_time->flags |= PARSEB_POWERUP; 545c0b746e5SOllivier Robert 546c0b746e5SOllivier Robert /* 547c0b746e5SOllivier Robert * at least one sv seen - time (for last position) 548c0b746e5SOllivier Robert */ 549c0b746e5SOllivier Robert if (f[1] == '*') 550c0b746e5SOllivier Robert clock_time->flags |= PARSEB_NOSYNC; 551c0b746e5SOllivier Robert else 552c0b746e5SOllivier Robert if (!(clock_time->flags & PARSEB_POWERUP)) 553c0b746e5SOllivier Robert clock_time->flags |= PARSEB_POSITION; 554c0b746e5SOllivier Robert 555c0b746e5SOllivier Robert /* 556c0b746e5SOllivier Robert * oncoming zone switch 557c0b746e5SOllivier Robert */ 558c0b746e5SOllivier Robert if (f[3] == '!') 559c0b746e5SOllivier Robert clock_time->flags |= PARSEB_ANNOUNCE; 560c0b746e5SOllivier Robert 561c0b746e5SOllivier Robert /* 562c0b746e5SOllivier Robert * oncoming leap second 563c0b746e5SOllivier Robert * 'a' code not confirmed - earth is not 564c0b746e5SOllivier Robert * expected to speed up 565c0b746e5SOllivier Robert */ 566c0b746e5SOllivier Robert if (f[4] == 'A') 567c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPADD; 568c0b746e5SOllivier Robert 569c0b746e5SOllivier Robert if (f[4] == 'a') 570c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPDEL; 571c0b746e5SOllivier Robert 572c0b746e5SOllivier Robert /* 573c0b746e5SOllivier Robert * f[5] == ' ' 574c0b746e5SOllivier Robert */ 575c0b746e5SOllivier Robert 576c0b746e5SOllivier Robert /* 577c0b746e5SOllivier Robert * this is the leap second 578c0b746e5SOllivier Robert */ 579c0b746e5SOllivier Robert if ((f[6] == 'L') || (clock_time->second == 60)) 580c0b746e5SOllivier Robert clock_time->flags |= PARSEB_LEAPSECOND; 581c0b746e5SOllivier Robert 582c0b746e5SOllivier Robert return CVT_OK; 583c0b746e5SOllivier Robert } 584c0b746e5SOllivier Robert } 585c0b746e5SOllivier Robert } 586c0b746e5SOllivier Robert 587c0b746e5SOllivier Robert /* 588a25439b6SCy Schubert * parse_inp_fnc_t gps_input 589c0b746e5SOllivier Robert * 590c0b746e5SOllivier Robert * grep binary data from input stream 591c0b746e5SOllivier Robert */ 592c0b746e5SOllivier Robert static u_long 593c0b746e5SOllivier Robert gps_input( 594c0b746e5SOllivier Robert parse_t *parseio, 595a25439b6SCy Schubert char ch, 596c0b746e5SOllivier Robert timestamp_t *tstamp 597c0b746e5SOllivier Robert ) 598c0b746e5SOllivier Robert { 599c0b746e5SOllivier Robert CSUM calc_csum; /* used to compare the incoming csums */ 600c0b746e5SOllivier Robert GPS_MSG_HDR header; 601c0b746e5SOllivier Robert struct msg_buf *msg_buf; 602c0b746e5SOllivier Robert 603c0b746e5SOllivier Robert msg_buf = (struct msg_buf *)parseio->parse_pdata; 604c0b746e5SOllivier Robert 6053311ff84SXin LI parseprintf(DD_PARSE, ("gps_input(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 606c0b746e5SOllivier Robert 607c0b746e5SOllivier Robert if (!msg_buf) 608c0b746e5SOllivier Robert return PARSE_INP_SKIP; 609c0b746e5SOllivier Robert 610c0b746e5SOllivier Robert if ( msg_buf->phase == MBG_NONE ) 611c0b746e5SOllivier Robert { /* not receiving yet */ 612c0b746e5SOllivier Robert switch (ch) 613c0b746e5SOllivier Robert { 614c0b746e5SOllivier Robert case SOH: 615c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: SOH seen\n")); 616c0b746e5SOllivier Robert 617c0b746e5SOllivier Robert msg_buf->len = sizeof( header ); /* prepare to receive msg header */ 618c0b746e5SOllivier Robert msg_buf->phase = MBG_HEADER; /* receiving header */ 619c0b746e5SOllivier Robert break; 620c0b746e5SOllivier Robert 621c0b746e5SOllivier Robert case STX: 622c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: STX seen\n")); 623c0b746e5SOllivier Robert 624c0b746e5SOllivier Robert msg_buf->len = 0; 625c0b746e5SOllivier Robert msg_buf->phase = MBG_STRING; /* prepare to receive ASCII ETX delimited message */ 626c0b746e5SOllivier Robert parseio->parse_index = 1; 627c0b746e5SOllivier Robert parseio->parse_data[0] = ch; 628c0b746e5SOllivier Robert break; 629c0b746e5SOllivier Robert 630c0b746e5SOllivier Robert default: 631c0b746e5SOllivier Robert return PARSE_INP_SKIP; /* keep searching */ 632c0b746e5SOllivier Robert } 633c0b746e5SOllivier Robert 634c0b746e5SOllivier Robert parseio->parse_dtime.parse_msglen = 1; /* reset buffer pointer */ 635c0b746e5SOllivier Robert parseio->parse_dtime.parse_msg[0] = ch; /* fill in first character */ 636c0b746e5SOllivier Robert parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ 637c0b746e5SOllivier Robert return PARSE_INP_SKIP; 638c0b746e5SOllivier Robert } 639c0b746e5SOllivier Robert 640c0b746e5SOllivier Robert /* SOH/STX has already been received */ 641c0b746e5SOllivier Robert 642c0b746e5SOllivier Robert /* save incoming character in both buffers if needbe */ 643c0b746e5SOllivier Robert if ((msg_buf->phase == MBG_STRING) && 644c0b746e5SOllivier Robert (parseio->parse_index < parseio->parse_dsize)) 645c0b746e5SOllivier Robert parseio->parse_data[parseio->parse_index++] = ch; 646c0b746e5SOllivier Robert 647c0b746e5SOllivier Robert parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; 648c0b746e5SOllivier Robert 649c0b746e5SOllivier Robert if (parseio->parse_dtime.parse_msglen > sizeof(parseio->parse_dtime.parse_msg)) 650c0b746e5SOllivier Robert { 651c0b746e5SOllivier Robert msg_buf->phase = MBG_NONE; /* buffer overflow - discard */ 652c0b746e5SOllivier Robert parseio->parse_data[parseio->parse_index] = '\0'; 653c0b746e5SOllivier Robert memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); 654ea906c41SOllivier Robert parseio->parse_ldsize = parseio->parse_index; 655c0b746e5SOllivier Robert return PARSE_INP_DATA; 656c0b746e5SOllivier Robert } 657c0b746e5SOllivier Robert 658c0b746e5SOllivier Robert switch (msg_buf->phase) 659c0b746e5SOllivier Robert { 660c0b746e5SOllivier Robert case MBG_HEADER: 661c0b746e5SOllivier Robert case MBG_DATA: 662c0b746e5SOllivier Robert msg_buf->len--; 663c0b746e5SOllivier Robert 664c0b746e5SOllivier Robert if ( msg_buf->len ) /* transfer not complete */ 665c0b746e5SOllivier Robert return PARSE_INP_SKIP; 666c0b746e5SOllivier Robert 667c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: %s complete\n", (msg_buf->phase == MBG_DATA) ? "data" : "header")); 668c0b746e5SOllivier Robert 669c0b746e5SOllivier Robert break; 670c0b746e5SOllivier Robert 671c0b746e5SOllivier Robert case MBG_STRING: 672c0b746e5SOllivier Robert if ((ch == ETX) || (parseio->parse_index >= parseio->parse_dsize)) 673c0b746e5SOllivier Robert { 674c0b746e5SOllivier Robert msg_buf->phase = MBG_NONE; 675c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: string complete\n")); 676c0b746e5SOllivier Robert parseio->parse_data[parseio->parse_index] = '\0'; 677c0b746e5SOllivier Robert memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); 678ea906c41SOllivier Robert parseio->parse_ldsize = parseio->parse_index; 679c0b746e5SOllivier Robert parseio->parse_index = 0; 680c0b746e5SOllivier Robert return PARSE_INP_TIME; 681c0b746e5SOllivier Robert } 682c0b746e5SOllivier Robert else 683c0b746e5SOllivier Robert { 684c0b746e5SOllivier Robert return PARSE_INP_SKIP; 685c0b746e5SOllivier Robert } 686c0b746e5SOllivier Robert } 687c0b746e5SOllivier Robert 688c0b746e5SOllivier Robert /* cnt == 0, so the header or the whole message is complete */ 689c0b746e5SOllivier Robert 690c0b746e5SOllivier Robert if ( msg_buf->phase == MBG_HEADER ) 691c0b746e5SOllivier Robert { /* header complete now */ 692c0b746e5SOllivier Robert unsigned char *datap = parseio->parse_dtime.parse_msg + 1; 693c0b746e5SOllivier Robert 694c0b746e5SOllivier Robert get_mbg_header(&datap, &header); 695c0b746e5SOllivier Robert 696c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: header: cmd 0x%x, len %d, dcsum 0x%x, hcsum 0x%x\n", 697a25439b6SCy Schubert (int)header.cmd, (int)header.len, (int)header.data_csum, 698a25439b6SCy Schubert (int)header.hdr_csum)); 699c0b746e5SOllivier Robert 700c0b746e5SOllivier Robert 701c0b746e5SOllivier Robert calc_csum = mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg + 1, (unsigned short)6 ); 702c0b746e5SOllivier Robert 703a25439b6SCy Schubert if ( calc_csum != header.hdr_csum ) 704c0b746e5SOllivier Robert { 705c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: header checksum mismatch expected 0x%x, got 0x%x\n", 706c0b746e5SOllivier Robert (int)calc_csum, (int)mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg, (unsigned short)6 ))); 707c0b746e5SOllivier Robert 708c0b746e5SOllivier Robert msg_buf->phase = MBG_NONE; /* back to hunting mode */ 709c0b746e5SOllivier Robert return PARSE_INP_DATA; /* invalid header checksum received - pass up for detection */ 710c0b746e5SOllivier Robert } 711c0b746e5SOllivier Robert 712a25439b6SCy Schubert if ((header.len == 0) || /* no data to wait for */ 713a25439b6SCy Schubert (header.len >= (sizeof (parseio->parse_dtime.parse_msg) - sizeof(header) - 1))) /* blows anything we have space for */ 714c0b746e5SOllivier Robert { 715c0b746e5SOllivier Robert msg_buf->phase = MBG_NONE; /* back to hunting mode */ 716a25439b6SCy Schubert return (header.len == 0) ? PARSE_INP_DATA : PARSE_INP_SKIP; /* message complete/throwaway */ 717c0b746e5SOllivier Robert } 718c0b746e5SOllivier Robert 719a25439b6SCy Schubert parseprintf(DD_PARSE, ("gps_input: expecting %d bytes of data message\n", (int)header.len)); 720c0b746e5SOllivier Robert 721a25439b6SCy Schubert msg_buf->len = header.len;/* save number of bytes to wait for */ 722c0b746e5SOllivier Robert msg_buf->phase = MBG_DATA; /* flag header already complete */ 723c0b746e5SOllivier Robert return PARSE_INP_SKIP; 724c0b746e5SOllivier Robert } 725c0b746e5SOllivier Robert 726c0b746e5SOllivier Robert parseprintf(DD_PARSE, ("gps_input: message data complete\n")); 727c0b746e5SOllivier Robert 728c0b746e5SOllivier Robert /* Header and data have been received. The header checksum has been */ 729c0b746e5SOllivier Robert /* checked */ 730c0b746e5SOllivier Robert 731c0b746e5SOllivier Robert msg_buf->phase = MBG_NONE; /* back to hunting mode */ 732c0b746e5SOllivier Robert return PARSE_INP_DATA; /* message complete, must be evaluated */ 733c0b746e5SOllivier Robert } 734c0b746e5SOllivier Robert 735c0b746e5SOllivier Robert #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_MEINBERG) */ 736*f5f40dd6SCy Schubert NONEMPTY_TRANSLATION_UNIT 737c0b746e5SOllivier Robert #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_MEINBERG) */ 738c0b746e5SOllivier Robert 739c0b746e5SOllivier Robert /* 740c0b746e5SOllivier Robert * History: 741c0b746e5SOllivier Robert * 742c0b746e5SOllivier Robert * clk_meinberg.c,v 743ea906c41SOllivier Robert * Revision 4.12.2.1 2005/09/25 10:22:35 kardel 744ea906c41SOllivier Robert * cleanup buffer bounds 745ea906c41SOllivier Robert * 746ea906c41SOllivier Robert * Revision 4.12 2005/04/16 17:32:10 kardel 747ea906c41SOllivier Robert * update copyright 748ea906c41SOllivier Robert * 749ea906c41SOllivier Robert * Revision 4.11 2004/11/14 15:29:41 kardel 750ea906c41SOllivier Robert * support PPSAPI, upgrade Copyright to Berkeley style 751ea906c41SOllivier Robert * 752a151a66cSOllivier Robert * Revision 4.8 1999/11/28 09:13:50 kardel 753a151a66cSOllivier Robert * RECON_4_0_98F 754a151a66cSOllivier Robert * 755c0b746e5SOllivier Robert * Revision 4.7 1999/02/21 11:09:14 kardel 756c0b746e5SOllivier Robert * cleanup 757c0b746e5SOllivier Robert * 758c0b746e5SOllivier Robert * Revision 4.6 1998/06/14 21:09:36 kardel 759c0b746e5SOllivier Robert * Sun acc cleanup 760c0b746e5SOllivier Robert * 761c0b746e5SOllivier Robert * Revision 4.5 1998/06/13 15:18:54 kardel 762c0b746e5SOllivier Robert * fix mem*() to b*() function macro emulation 763c0b746e5SOllivier Robert * 764c0b746e5SOllivier Robert * Revision 4.4 1998/06/13 12:03:23 kardel 765c0b746e5SOllivier Robert * fix SYSV clock name clash 766c0b746e5SOllivier Robert * 767c0b746e5SOllivier Robert * Revision 4.3 1998/06/12 15:22:28 kardel 768c0b746e5SOllivier Robert * fix prototypes 769c0b746e5SOllivier Robert * 770c0b746e5SOllivier Robert * Revision 4.2 1998/05/24 16:14:42 kardel 771c0b746e5SOllivier Robert * support current Meinberg standard data formats 772c0b746e5SOllivier Robert * 773c0b746e5SOllivier Robert * Revision 4.1 1998/05/24 09:39:52 kardel 774c0b746e5SOllivier Robert * implementation of the new IO handling model 775c0b746e5SOllivier Robert * 776c0b746e5SOllivier Robert * Revision 4.0 1998/04/10 19:45:29 kardel 777c0b746e5SOllivier Robert * Start 4.0 release version numbering 778c0b746e5SOllivier Robert * 779c0b746e5SOllivier Robert * from V3 3.23 - log info deleted 1998/04/11 kardel 780c0b746e5SOllivier Robert * 781c0b746e5SOllivier Robert */ 782