12b15cb3dSCy Schubert ////////////////////////////////////////////////////////////////////////////// 22b15cb3dSCy Schubert // Copyright (c) 2009,2012 - 32b15cb3dSCy Schubert // Schweitzer Engineering Laboratories, Inc. <opensource@selinc.com> 42b15cb3dSCy Schubert ////////////////////////////////////////////////////////////////////////////// 52b15cb3dSCy Schubert 62b15cb3dSCy Schubert // Need to have _XOPEN_SOURCE defined for time.h to give the 72b15cb3dSCy Schubert // correct strptime signature. As per feature_test_macros(7), 82b15cb3dSCy Schubert // define this before including any header files. 92b15cb3dSCy Schubert 102b15cb3dSCy Schubert // #ifndef _XOPEN_SOURCE 112b15cb3dSCy Schubert // #define _XOPEN_SOURCE 122b15cb3dSCy Schubert // #endif 132b15cb3dSCy Schubert 142b15cb3dSCy Schubert #ifdef HAVE_CONFIG_H 152b15cb3dSCy Schubert # include <config.h> 162b15cb3dSCy Schubert #endif 172b15cb3dSCy Schubert 182b15cb3dSCy Schubert #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X) 192b15cb3dSCy Schubert 202b15cb3dSCy Schubert #include "ntp_syslog.h" 212b15cb3dSCy Schubert #include "ntp_types.h" 222b15cb3dSCy Schubert #include "ntp_fp.h" 232b15cb3dSCy Schubert #include "ntp_unixtime.h" 242b15cb3dSCy Schubert #include "ntp_calendar.h" 252b15cb3dSCy Schubert #include "ntp_machine.h" 262b15cb3dSCy Schubert #include "ntp_stdlib.h" 272b15cb3dSCy Schubert 282b15cb3dSCy Schubert #include "parse.h" 292b15cb3dSCy Schubert 302b15cb3dSCy Schubert #ifndef PARSESTREAM 312b15cb3dSCy Schubert # include <stdio.h> 322b15cb3dSCy Schubert #else 332b15cb3dSCy Schubert # include "sys/parsestreams.h" 342b15cb3dSCy Schubert #endif 352b15cb3dSCy Schubert 362b15cb3dSCy Schubert #include <time.h> 372b15cb3dSCy Schubert 382b15cb3dSCy Schubert ////////////////////////////////////////////////////////////////////////////// 392b15cb3dSCy Schubert // The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n' 402b15cb3dSCy Schubert // where q = ' ' locked 412b15cb3dSCy Schubert // '.' <1 us 422b15cb3dSCy Schubert // '*' <10 us 432b15cb3dSCy Schubert // '#' <100 us 442b15cb3dSCy Schubert // '?' >100 us 452b15cb3dSCy Schubert // 462b15cb3dSCy Schubert // Based on this we need to recored the stime when we receive the <SOH> 472b15cb3dSCy Schubert // character and end it when we see the \n. 482b15cb3dSCy Schubert // 492b15cb3dSCy Schubert // The q or quality character indicates satellite lock and sync. For the 502b15cb3dSCy Schubert // purposes of NTP we are going to call it valid when we receive anything but 512b15cb3dSCy Schubert // a '?'. But we are only going to call it synced when we receive a ' ' 522b15cb3dSCy Schubert ////////////////////////////////////////////////////////////////////////////// 532b15cb3dSCy Schubert 54a25439b6SCy Schubert static parse_inp_fnc_t inp_sel240x; 55a25439b6SCy Schubert static parse_cvt_fnc_t cvt_sel240x; 562b15cb3dSCy Schubert 572b15cb3dSCy Schubert // Parse clock format structure describing the message above 582b15cb3dSCy Schubert static struct format sel240x_fmt = 592b15cb3dSCy Schubert { { { 6, 3 }, 602b15cb3dSCy Schubert { 0, 0 }, 612b15cb3dSCy Schubert { 1, 4 }, 622b15cb3dSCy Schubert { 10, 2 }, 632b15cb3dSCy Schubert { 13, 2 }, 642b15cb3dSCy Schubert { 16, 2 }, 652b15cb3dSCy Schubert { 0, 0 }, 662b15cb3dSCy Schubert { 0, 0 }, 672b15cb3dSCy Schubert { 0, 0 }, 682b15cb3dSCy Schubert { 0, 0 }, 692b15cb3dSCy Schubert { 0, 0 }, 702b15cb3dSCy Schubert { 0, 0 } 712b15cb3dSCy Schubert }, 722b15cb3dSCy Schubert (const unsigned char *)"\x01 : : : : \x0d\x0a", 732b15cb3dSCy Schubert 0 742b15cb3dSCy Schubert }; 752b15cb3dSCy Schubert 762b15cb3dSCy Schubert // Structure desctibing the parser 772b15cb3dSCy Schubert clockformat_t clock_sel240x = 782b15cb3dSCy Schubert { 792b15cb3dSCy Schubert inp_sel240x, 802b15cb3dSCy Schubert cvt_sel240x, 812b15cb3dSCy Schubert pps_one, 822b15cb3dSCy Schubert (void*)&sel240x_fmt, 832b15cb3dSCy Schubert "SEL B8", 842b15cb3dSCy Schubert 25, 852b15cb3dSCy Schubert 0 862b15cb3dSCy Schubert }; 872b15cb3dSCy Schubert 882b15cb3dSCy Schubert ////////////////////////////////////////////////////////////////////////////// 892b15cb3dSCy Schubert static unsigned long 902b15cb3dSCy Schubert inp_sel240x( parse_t *parseio, 91a25439b6SCy Schubert char ch, 922b15cb3dSCy Schubert timestamp_t *tstamp 932b15cb3dSCy Schubert ) 942b15cb3dSCy Schubert { 952b15cb3dSCy Schubert unsigned long rc; 962b15cb3dSCy Schubert 972b15cb3dSCy Schubert parseprintf( DD_PARSE, 982b15cb3dSCy Schubert ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch)); 992b15cb3dSCy Schubert 1002b15cb3dSCy Schubert switch( ch ) 1012b15cb3dSCy Schubert { 1022b15cb3dSCy Schubert case '\x01': 1032b15cb3dSCy Schubert parseio->parse_index = 1; 1042b15cb3dSCy Schubert parseio->parse_data[0] = ch; 1052b15cb3dSCy Schubert parseio->parse_dtime.parse_stime = *tstamp; 1062b15cb3dSCy Schubert rc = PARSE_INP_SKIP; 1072b15cb3dSCy Schubert break; 1082b15cb3dSCy Schubert case '\n': 1092b15cb3dSCy Schubert if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP ) 1102b15cb3dSCy Schubert { 1112b15cb3dSCy Schubert rc = parse_end( parseio ); 1122b15cb3dSCy Schubert } 1132b15cb3dSCy Schubert break; 1142b15cb3dSCy Schubert default: 1152b15cb3dSCy Schubert rc = parse_addchar( parseio, ch ); 1162b15cb3dSCy Schubert } 1172b15cb3dSCy Schubert 1182b15cb3dSCy Schubert return rc; 1192b15cb3dSCy Schubert } 1202b15cb3dSCy Schubert 1212b15cb3dSCy Schubert ////////////////////////////////////////////////////////////////////////////// 1222b15cb3dSCy Schubert static unsigned long 1232b15cb3dSCy Schubert cvt_sel240x( unsigned char *buffer, 1242b15cb3dSCy Schubert int size, 1252b15cb3dSCy Schubert struct format *format, 1262b15cb3dSCy Schubert clocktime_t *clock_time, 1272b15cb3dSCy Schubert void *local 1282b15cb3dSCy Schubert ) 1292b15cb3dSCy Schubert { 1302b15cb3dSCy Schubert unsigned long rc = CVT_NONE; 1312b15cb3dSCy Schubert 1322b15cb3dSCy Schubert if( Strok(buffer, format->fixed_string) ) 1332b15cb3dSCy Schubert { 1342b15cb3dSCy Schubert struct tm ptime; 1352b15cb3dSCy Schubert buffer++; 1362b15cb3dSCy Schubert buffer = (unsigned char *) strptime( 1372b15cb3dSCy Schubert (const char *)buffer, "%Y:%j:%H:%M:%S", &ptime ); 1382b15cb3dSCy Schubert if( *(buffer+1) != '\x0d' ) 1392b15cb3dSCy Schubert { 1402b15cb3dSCy Schubert rc = CVT_FAIL | CVT_BADFMT; 1412b15cb3dSCy Schubert } 1422b15cb3dSCy Schubert else 1432b15cb3dSCy Schubert { 1442b15cb3dSCy Schubert clock_time->day = ptime.tm_mday; 1452b15cb3dSCy Schubert clock_time->month = ptime.tm_mon + 1; 1462b15cb3dSCy Schubert clock_time->year = ptime.tm_year + 1900; 1472b15cb3dSCy Schubert clock_time->hour = ptime.tm_hour; 1482b15cb3dSCy Schubert clock_time->minute = ptime.tm_min; 1492b15cb3dSCy Schubert clock_time->second = ptime.tm_sec; 1502b15cb3dSCy Schubert clock_time->usecond = 0; 1512b15cb3dSCy Schubert clock_time->utcoffset = 0; 1522b15cb3dSCy Schubert clock_time->flags = PARSEB_UTC; 1532b15cb3dSCy Schubert 1542b15cb3dSCy Schubert if( *buffer == '?' ) 1552b15cb3dSCy Schubert { 1562b15cb3dSCy Schubert clock_time->flags |= PARSEB_POWERUP; 1572b15cb3dSCy Schubert } 1582b15cb3dSCy Schubert else if( *buffer != ' ' ) 1592b15cb3dSCy Schubert { 1602b15cb3dSCy Schubert clock_time->flags |= PARSEB_NOSYNC; 1612b15cb3dSCy Schubert } 1622b15cb3dSCy Schubert 1632b15cb3dSCy Schubert rc = CVT_OK; 1642b15cb3dSCy Schubert } 1652b15cb3dSCy Schubert } 1662b15cb3dSCy Schubert 1672b15cb3dSCy Schubert return rc; 1682b15cb3dSCy Schubert } 1692b15cb3dSCy Schubert 1702b15cb3dSCy Schubert #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 171*f5f40dd6SCy Schubert NONEMPTY_TRANSLATION_UNIT 1722b15cb3dSCy Schubert #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 173