summaryrefslogtreecommitdiff
path: root/libparse/clk_sel240x.c
blob: b1390b4cefb1b4b4d27f4f056a85f47d49f1f103 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2009,2012 -
//        Schweitzer Engineering Laboratories, Inc. <opensource@selinc.com>
//////////////////////////////////////////////////////////////////////////////

// Need to have _XOPEN_SOURCE defined for time.h to give the
// correct strptime signature.  As per feature_test_macros(7),
// define this before including any header files.

// #ifndef _XOPEN_SOURCE
// #define _XOPEN_SOURCE
// #endif

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X)

#include "ntp_syslog.h"
#include "ntp_types.h"
#include "ntp_fp.h"
#include "ntp_unixtime.h"
#include "ntp_calendar.h"
#include "ntp_machine.h"
#include "ntp_stdlib.h"

#include "parse.h"

#ifndef PARSESTREAM
# include <stdio.h>
#else
# include "sys/parsestreams.h"
#endif

#include <time.h>

//////////////////////////////////////////////////////////////////////////////
// The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n'
//    where q = ' ' locked
//              '.' <1 us
//              '*' <10 us
//              '#' <100 us
//              '?' >100 us
//
// Based on this we need to recored the stime when we receive the <SOH>
// character and end it when we see the \n.
//
// The q or quality character indicates satellite lock and sync.   For the
// purposes of NTP we are going to call it valid when we receive anything but
// a '?'.  But we are only going to call it synced when we receive a ' '
//////////////////////////////////////////////////////////////////////////////

static parse_inp_fnc_t inp_sel240x;
static parse_cvt_fnc_t cvt_sel240x;

// Parse clock format structure describing the message above
static struct format sel240x_fmt =
{ { {  6, 3 },
    {  0, 0 },
    {  1, 4 },
    { 10, 2 },
    { 13, 2 },
    { 16, 2 },
    {  0, 0 },
    {  0, 0 },
    {  0, 0 },
    {  0, 0 },
    {  0, 0 },
    {  0, 0 }
  },
  (const unsigned char *)"\x01    :   :  :  :   \x0d\x0a",
  0
};

// Structure desctibing the parser
clockformat_t clock_sel240x =
{
	inp_sel240x,
	cvt_sel240x,
	pps_one,
	(void*)&sel240x_fmt,
	"SEL B8",
	25,
	0
};

//////////////////////////////////////////////////////////////////////////////
static unsigned long
inp_sel240x( parse_t      *parseio,
	     char         ch,
	     timestamp_t  *tstamp
	   )
{
	unsigned long rc;

	parseprintf( DD_PARSE,
	             ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch));

	switch( ch )
	{
	case '\x01':
		parseio->parse_index = 1;
		parseio->parse_data[0] = ch;
		parseio->parse_dtime.parse_stime = *tstamp;
		rc = PARSE_INP_SKIP;
		break;
	case '\n':
		if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP )
		{
			rc = parse_end( parseio );
		}
		break;
	default:
		rc = parse_addchar( parseio, ch );
	}

	return rc;
}

//////////////////////////////////////////////////////////////////////////////
static unsigned long
cvt_sel240x( unsigned char *buffer,
	     int            size,
	     struct format *format,
	     clocktime_t   *clock_time,
	     void          *local
	   )
{
	unsigned long rc = CVT_NONE;

	if( Strok(buffer, format->fixed_string) )
	{
		struct tm ptime;
		buffer++;
		buffer = (unsigned char *) strptime(
			(const char *)buffer, "%Y:%j:%H:%M:%S", &ptime );
		if( *(buffer+1) != '\x0d' )
		{
			rc = CVT_FAIL | CVT_BADFMT;
		}
		else
		{
			clock_time->day = ptime.tm_mday;
			clock_time->month = ptime.tm_mon + 1;
			clock_time->year = ptime.tm_year + 1900;
			clock_time->hour = ptime.tm_hour;
			clock_time->minute = ptime.tm_min;
			clock_time->second = ptime.tm_sec;
			clock_time->usecond = 0;
			clock_time->utcoffset = 0;
			clock_time->flags = PARSEB_UTC;

			if( *buffer == '?' )
			{
				clock_time->flags |= PARSEB_POWERUP;
			}
			else if( *buffer != ' ' )
			{
				clock_time->flags |= PARSEB_NOSYNC;
			}

			rc = CVT_OK;
		}
	}

	return rc;
}

#else  /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */
int clk_sel240x_bs;
#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */