clk_sel240x.c revision 275970
193836Stmm//////////////////////////////////////////////////////////////////////////////
293836Stmm// Copyright (c) 2009,2012 -
393836Stmm//        Schweitzer Engineering Laboratories, Inc. <opensource@selinc.com>
493836Stmm//////////////////////////////////////////////////////////////////////////////
593836Stmm
693836Stmm// Need to have _XOPEN_SOURCE defined for time.h to give the
793836Stmm// correct strptime signature.  As per feature_test_macros(7),
893836Stmm// define this before including any header files.
993836Stmm
1093836Stmm// #ifndef _XOPEN_SOURCE
1193836Stmm// #define _XOPEN_SOURCE
1293836Stmm// #endif
1393836Stmm
1493836Stmm#ifdef HAVE_CONFIG_H
1593836Stmm# include <config.h>
1693836Stmm#endif
1793836Stmm
1893836Stmm#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X)
1993836Stmm
2093836Stmm#include "ntp_syslog.h"
2193836Stmm#include "ntp_types.h"
2293836Stmm#include "ntp_fp.h"
2393836Stmm#include "ntp_unixtime.h"
2493836Stmm#include "ntp_calendar.h"
2593836Stmm#include "ntp_machine.h"
2693836Stmm#include "ntp_stdlib.h"
2793836Stmm
2893836Stmm#include "parse.h"
2993836Stmm
3093836Stmm#ifndef PARSESTREAM
3193836Stmm# include <stdio.h>
3293836Stmm#else
3393836Stmm# include "sys/parsestreams.h"
3493836Stmm#endif
3593836Stmm
36137813Smarius#include <time.h>
3793836Stmm
3893836Stmm//////////////////////////////////////////////////////////////////////////////
39119418Sobrien// The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n'
40119418Sobrien//    where q = ' ' locked
41119418Sobrien//              '.' <1 us
4293836Stmm//              '*' <10 us
43137813Smarius//              '#' <100 us
4493836Stmm//              '?' >100 us
4593836Stmm//
4693836Stmm// Based on this we need to recored the stime when we receive the <SOH>
4793836Stmm// character and end it when we see the \n.
4893836Stmm//
4993836Stmm// The q or quality character indicates satellite lock and sync.   For the
50146416Smarius// purposes of NTP we are going to call it valid when we receive anything but
51146416Smarius// a '?'.  But we are only going to call it synced when we receive a ' '
52146416Smarius//////////////////////////////////////////////////////////////////////////////
53146416Smarius
5493836Stmmstatic unsigned long inp_sel240x( parse_t *parseio,
5593836Stmm		                  unsigned int ch,
5693836Stmm				  timestamp_t *tstamp);
57119352Smarcelstatic unsigned long cvt_sel240x( unsigned char *buffer,
58137813Smarius		                  int size,
5993836Stmm				  struct format *format,
6093836Stmm				  clocktime_t *clock_time,
6193836Stmm				  void *local );
62137813Smarius
63146416Smarius// Parse clock format structure describing the message above
64146416Smariusstatic struct format sel240x_fmt =
6593836Stmm{ { {  6, 3 },
6693836Stmm    {  0, 0 },
6793836Stmm    {  1, 4 },
6893836Stmm    { 10, 2 },
6993836Stmm    { 13, 2 },
7093836Stmm    { 16, 2 },
7193836Stmm    {  0, 0 },
7293836Stmm    {  0, 0 },
7393836Stmm    {  0, 0 },
7493836Stmm    {  0, 0 },
75137813Smarius    {  0, 0 },
7693836Stmm    {  0, 0 }
7793836Stmm  },
7893836Stmm  (const unsigned char *)"\x01    :   :  :  :   \x0d\x0a",
7993836Stmm  0
80137813Smarius};
8193836Stmm
8293836Stmm// Structure desctibing the parser
8393836Stmmclockformat_t clock_sel240x =
84146416Smarius{
8593836Stmm	inp_sel240x,
86137813Smarius	cvt_sel240x,
87137813Smarius	pps_one,
88146416Smarius	(void*)&sel240x_fmt,
89146416Smarius	"SEL B8",
90146416Smarius	25,
91146416Smarius	0
92146416Smarius};
93137813Smarius
9493836Stmm//////////////////////////////////////////////////////////////////////////////
9593836Stmmstatic unsigned long
96137813Smariusinp_sel240x( parse_t      *parseio,
9793836Stmm	     unsigned int ch,
9893836Stmm	     timestamp_t  *tstamp
9993836Stmm	   )
10093836Stmm{
10193836Stmm	unsigned long rc;
10293836Stmm
10393836Stmm	parseprintf( DD_PARSE,
10493836Stmm	             ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch));
105137813Smarius
106137813Smarius	switch( ch )
10793836Stmm	{
108137813Smarius	case '\x01':
109137813Smarius		parseio->parse_index = 1;
110137813Smarius		parseio->parse_data[0] = ch;
111137813Smarius		parseio->parse_dtime.parse_stime = *tstamp;
112137813Smarius		rc = PARSE_INP_SKIP;
113146416Smarius		break;
114146416Smarius	case '\n':
115146416Smarius		if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP )
116146416Smarius		{
117146416Smarius			rc = parse_end( parseio );
118146416Smarius		}
119146416Smarius		break;
120146416Smarius	default:
121146416Smarius		rc = parse_addchar( parseio, ch );
122135481Smarius	}
123135481Smarius
124146416Smarius	return rc;
125146416Smarius}
126146416Smarius
127146416Smarius//////////////////////////////////////////////////////////////////////////////
128146416Smariusstatic unsigned long
129146416Smariuscvt_sel240x( unsigned char *buffer,
130146416Smarius	     int            size,
131146416Smarius	     struct format *format,
132146416Smarius	     clocktime_t   *clock_time,
133146416Smarius	     void          *local
134146416Smarius	   )
135146416Smarius{
136146416Smarius	unsigned long rc = CVT_NONE;
137146416Smarius
138146416Smarius	if( Strok(buffer, format->fixed_string) )
139146416Smarius	{
140146416Smarius		struct tm ptime;
141146416Smarius		buffer++;
142146416Smarius		buffer = (unsigned char *) strptime(
14393836Stmm			(const char *)buffer, "%Y:%j:%H:%M:%S", &ptime );
14493836Stmm		if( *(buffer+1) != '\x0d' )
145146416Smarius		{
146146416Smarius			rc = CVT_FAIL | CVT_BADFMT;
147146416Smarius		}
148146416Smarius		else
149146416Smarius		{
150161837Smarius			clock_time->day = ptime.tm_mday;
151146416Smarius			clock_time->month = ptime.tm_mon + 1;
152146416Smarius			clock_time->year = ptime.tm_year + 1900;
15393836Stmm			clock_time->hour = ptime.tm_hour;
15493836Stmm			clock_time->minute = ptime.tm_min;
15593836Stmm			clock_time->second = ptime.tm_sec;
15693836Stmm			clock_time->usecond = 0;
15793836Stmm			clock_time->utcoffset = 0;
15893836Stmm			clock_time->flags = PARSEB_UTC;
15993836Stmm
16093836Stmm			if( *buffer == '?' )
16193836Stmm			{
16293836Stmm				clock_time->flags |= PARSEB_POWERUP;
163137813Smarius			}
164137813Smarius			else if( *buffer != ' ' )
16593836Stmm			{
16693836Stmm				clock_time->flags |= PARSEB_NOSYNC;
167146416Smarius			}
16893836Stmm
169137813Smarius			rc = CVT_OK;
170137813Smarius		}
171137813Smarius	}
172146416Smarius
17393836Stmm	return rc;
174137813Smarius}
17593836Stmm
176137813Smarius#else  /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */
17793836Stmmint clk_sel240x_bs;
178137813Smarius#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */
179135481Smarius