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