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