1 /* $NetBSD: clk_sel240x.c,v 1.1.1.1 2013/12/27 23:30:49 christos Exp $ */ 2 3 ////////////////////////////////////////////////////////////////////////////// 4 // Copyright (c) 2009,2012 - 5 // Schweitzer Engineering Laboratories, Inc. <opensource@selinc.com> 6 ////////////////////////////////////////////////////////////////////////////// 7 8 // Need to have _XOPEN_SOURCE defined for time.h to give the 9 // correct strptime signature. As per feature_test_macros(7), 10 // define this before including any header files. 11 12 // #ifndef _XOPEN_SOURCE 13 // #define _XOPEN_SOURCE 14 // #endif 15 16 #ifdef HAVE_CONFIG_H 17 # include <config.h> 18 #endif 19 20 #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X) 21 22 #include "ntp_syslog.h" 23 #include "ntp_types.h" 24 #include "ntp_fp.h" 25 #include "ntp_unixtime.h" 26 #include "ntp_calendar.h" 27 #include "ntp_machine.h" 28 #include "ntp_stdlib.h" 29 30 #include "parse.h" 31 32 #ifndef PARSESTREAM 33 # include <stdio.h> 34 #else 35 # include "sys/parsestreams.h" 36 #endif 37 38 #include <time.h> 39 40 ////////////////////////////////////////////////////////////////////////////// 41 // The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n' 42 // where q = ' ' locked 43 // '.' <1 us 44 // '*' <10 us 45 // '#' <100 us 46 // '?' >100 us 47 // 48 // Based on this we need to recored the stime when we receive the <SOH> 49 // character and end it when we see the \n. 50 // 51 // The q or quality character indicates satellite lock and sync. For the 52 // purposes of NTP we are going to call it valid when we receive anything but 53 // a '?'. But we are only going to call it synced when we receive a ' ' 54 ////////////////////////////////////////////////////////////////////////////// 55 56 static unsigned long inp_sel240x( parse_t *parseio, 57 unsigned int ch, 58 timestamp_t *tstamp); 59 static unsigned long cvt_sel240x( unsigned char *buffer, 60 int size, 61 struct format *format, 62 clocktime_t *clock_time, 63 void *local ); 64 65 // Parse clock format structure describing the message above 66 static struct format sel240x_fmt = 67 { { { 6, 3 }, 68 { 0, 0 }, 69 { 1, 4 }, 70 { 10, 2 }, 71 { 13, 2 }, 72 { 16, 2 }, 73 { 0, 0 }, 74 { 0, 0 }, 75 { 0, 0 }, 76 { 0, 0 }, 77 { 0, 0 }, 78 { 0, 0 } 79 }, 80 (const unsigned char *)"\x01 : : : : \x0d\x0a", 81 0 82 }; 83 84 // Structure desctibing the parser 85 clockformat_t clock_sel240x = 86 { 87 inp_sel240x, 88 cvt_sel240x, 89 pps_one, 90 (void*)&sel240x_fmt, 91 "SEL B8", 92 25, 93 0 94 }; 95 96 ////////////////////////////////////////////////////////////////////////////// 97 static unsigned long 98 inp_sel240x( parse_t *parseio, 99 unsigned int ch, 100 timestamp_t *tstamp 101 ) 102 { 103 unsigned long rc; 104 105 parseprintf( DD_PARSE, 106 ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch)); 107 108 switch( ch ) 109 { 110 case '\x01': 111 parseio->parse_index = 1; 112 parseio->parse_data[0] = ch; 113 parseio->parse_dtime.parse_stime = *tstamp; 114 rc = PARSE_INP_SKIP; 115 break; 116 case '\n': 117 if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP ) 118 { 119 rc = parse_end( parseio ); 120 } 121 break; 122 default: 123 rc = parse_addchar( parseio, ch ); 124 } 125 126 return rc; 127 } 128 129 ////////////////////////////////////////////////////////////////////////////// 130 static unsigned long 131 cvt_sel240x( unsigned char *buffer, 132 int size, 133 struct format *format, 134 clocktime_t *clock_time, 135 void *local 136 ) 137 { 138 unsigned long rc = CVT_NONE; 139 140 if( Strok(buffer, format->fixed_string) ) 141 { 142 struct tm ptime; 143 buffer++; 144 buffer = (unsigned char *) strptime( 145 (const char *)buffer, "%Y:%j:%H:%M:%S", &ptime ); 146 if( *(buffer+1) != '\x0d' ) 147 { 148 rc = CVT_FAIL | CVT_BADFMT; 149 } 150 else 151 { 152 clock_time->day = ptime.tm_mday; 153 clock_time->month = ptime.tm_mon + 1; 154 clock_time->year = ptime.tm_year + 1900; 155 clock_time->hour = ptime.tm_hour; 156 clock_time->minute = ptime.tm_min; 157 clock_time->second = ptime.tm_sec; 158 clock_time->usecond = 0; 159 clock_time->utcoffset = 0; 160 clock_time->flags = PARSEB_UTC; 161 162 if( *buffer == '?' ) 163 { 164 clock_time->flags |= PARSEB_POWERUP; 165 } 166 else if( *buffer != ' ' ) 167 { 168 clock_time->flags |= PARSEB_NOSYNC; 169 } 170 171 rc = CVT_OK; 172 } 173 } 174 175 return rc; 176 } 177 178 #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 179 int clk_sel240x_bs; 180 #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 181