1290001Sglebius////////////////////////////////////////////////////////////////////////////// 2290001Sglebius// Copyright (c) 2009,2012 - 3290001Sglebius// Schweitzer Engineering Laboratories, Inc. <opensource@selinc.com> 4290001Sglebius////////////////////////////////////////////////////////////////////////////// 5290001Sglebius 6290001Sglebius// Need to have _XOPEN_SOURCE defined for time.h to give the 7290001Sglebius// correct strptime signature. As per feature_test_macros(7), 8290001Sglebius// define this before including any header files. 9290001Sglebius 10290001Sglebius// #ifndef _XOPEN_SOURCE 11290001Sglebius// #define _XOPEN_SOURCE 12290001Sglebius// #endif 13290001Sglebius 14290001Sglebius#ifdef HAVE_CONFIG_H 15290001Sglebius# include <config.h> 16290001Sglebius#endif 17290001Sglebius 18290001Sglebius#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X) 19290001Sglebius 20290001Sglebius#include "ntp_syslog.h" 21290001Sglebius#include "ntp_types.h" 22290001Sglebius#include "ntp_fp.h" 23290001Sglebius#include "ntp_unixtime.h" 24290001Sglebius#include "ntp_calendar.h" 25290001Sglebius#include "ntp_machine.h" 26290001Sglebius#include "ntp_stdlib.h" 27290001Sglebius 28290001Sglebius#include "parse.h" 29290001Sglebius 30290001Sglebius#ifndef PARSESTREAM 31290001Sglebius# include <stdio.h> 32290001Sglebius#else 33290001Sglebius# include "sys/parsestreams.h" 34290001Sglebius#endif 35290001Sglebius 36290001Sglebius#include <time.h> 37290001Sglebius 38290001Sglebius////////////////////////////////////////////////////////////////////////////// 39290001Sglebius// The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n' 40290001Sglebius// where q = ' ' locked 41290001Sglebius// '.' <1 us 42290001Sglebius// '*' <10 us 43290001Sglebius// '#' <100 us 44290001Sglebius// '?' >100 us 45290001Sglebius// 46290001Sglebius// Based on this we need to recored the stime when we receive the <SOH> 47290001Sglebius// character and end it when we see the \n. 48290001Sglebius// 49290001Sglebius// The q or quality character indicates satellite lock and sync. For the 50290001Sglebius// purposes of NTP we are going to call it valid when we receive anything but 51290001Sglebius// a '?'. But we are only going to call it synced when we receive a ' ' 52290001Sglebius////////////////////////////////////////////////////////////////////////////// 53290001Sglebius 54290001Sglebiusstatic parse_inp_fnc_t inp_sel240x; 55290001Sglebiusstatic parse_cvt_fnc_t cvt_sel240x; 56290001Sglebius 57290001Sglebius// Parse clock format structure describing the message above 58290001Sglebiusstatic struct format sel240x_fmt = 59290001Sglebius{ { { 6, 3 }, 60290001Sglebius { 0, 0 }, 61290001Sglebius { 1, 4 }, 62290001Sglebius { 10, 2 }, 63290001Sglebius { 13, 2 }, 64290001Sglebius { 16, 2 }, 65290001Sglebius { 0, 0 }, 66290001Sglebius { 0, 0 }, 67290001Sglebius { 0, 0 }, 68290001Sglebius { 0, 0 }, 69290001Sglebius { 0, 0 }, 70290001Sglebius { 0, 0 } 71290001Sglebius }, 72290001Sglebius (const unsigned char *)"\x01 : : : : \x0d\x0a", 73290001Sglebius 0 74290001Sglebius}; 75290001Sglebius 76290001Sglebius// Structure desctibing the parser 77290001Sglebiusclockformat_t clock_sel240x = 78290001Sglebius{ 79290001Sglebius inp_sel240x, 80290001Sglebius cvt_sel240x, 81290001Sglebius pps_one, 82290001Sglebius (void*)&sel240x_fmt, 83290001Sglebius "SEL B8", 84290001Sglebius 25, 85290001Sglebius 0 86290001Sglebius}; 87290001Sglebius 88290001Sglebius////////////////////////////////////////////////////////////////////////////// 89290001Sglebiusstatic unsigned long 90290001Sglebiusinp_sel240x( parse_t *parseio, 91290001Sglebius char ch, 92290001Sglebius timestamp_t *tstamp 93290001Sglebius ) 94290001Sglebius{ 95290001Sglebius unsigned long rc; 96290001Sglebius 97290001Sglebius parseprintf( DD_PARSE, 98290001Sglebius ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch)); 99290001Sglebius 100290001Sglebius switch( ch ) 101290001Sglebius { 102290001Sglebius case '\x01': 103290001Sglebius parseio->parse_index = 1; 104290001Sglebius parseio->parse_data[0] = ch; 105290001Sglebius parseio->parse_dtime.parse_stime = *tstamp; 106290001Sglebius rc = PARSE_INP_SKIP; 107290001Sglebius break; 108290001Sglebius case '\n': 109290001Sglebius if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP ) 110290001Sglebius { 111290001Sglebius rc = parse_end( parseio ); 112290001Sglebius } 113290001Sglebius break; 114290001Sglebius default: 115290001Sglebius rc = parse_addchar( parseio, ch ); 116290001Sglebius } 117290001Sglebius 118290001Sglebius return rc; 119290001Sglebius} 120290001Sglebius 121290001Sglebius////////////////////////////////////////////////////////////////////////////// 122290001Sglebiusstatic unsigned long 123290001Sglebiuscvt_sel240x( unsigned char *buffer, 124290001Sglebius int size, 125290001Sglebius struct format *format, 126290001Sglebius clocktime_t *clock_time, 127290001Sglebius void *local 128290001Sglebius ) 129290001Sglebius{ 130290001Sglebius unsigned long rc = CVT_NONE; 131290001Sglebius 132290001Sglebius if( Strok(buffer, format->fixed_string) ) 133290001Sglebius { 134290001Sglebius struct tm ptime; 135290001Sglebius buffer++; 136290001Sglebius buffer = (unsigned char *) strptime( 137290001Sglebius (const char *)buffer, "%Y:%j:%H:%M:%S", &ptime ); 138290001Sglebius if( *(buffer+1) != '\x0d' ) 139290001Sglebius { 140290001Sglebius rc = CVT_FAIL | CVT_BADFMT; 141290001Sglebius } 142290001Sglebius else 143290001Sglebius { 144290001Sglebius clock_time->day = ptime.tm_mday; 145290001Sglebius clock_time->month = ptime.tm_mon + 1; 146290001Sglebius clock_time->year = ptime.tm_year + 1900; 147290001Sglebius clock_time->hour = ptime.tm_hour; 148290001Sglebius clock_time->minute = ptime.tm_min; 149290001Sglebius clock_time->second = ptime.tm_sec; 150290001Sglebius clock_time->usecond = 0; 151290001Sglebius clock_time->utcoffset = 0; 152290001Sglebius clock_time->flags = PARSEB_UTC; 153290001Sglebius 154290001Sglebius if( *buffer == '?' ) 155290001Sglebius { 156290001Sglebius clock_time->flags |= PARSEB_POWERUP; 157290001Sglebius } 158290001Sglebius else if( *buffer != ' ' ) 159290001Sglebius { 160290001Sglebius clock_time->flags |= PARSEB_NOSYNC; 161290001Sglebius } 162290001Sglebius 163290001Sglebius rc = CVT_OK; 164290001Sglebius } 165290001Sglebius } 166290001Sglebius 167290001Sglebius return rc; 168290001Sglebius} 169290001Sglebius 170290001Sglebius#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 171290001Sglebiusint clk_sel240x_bs; 172290001Sglebius#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 173