154359Sroberto#ifdef HAVE_CONFIG_H
254359Sroberto# include <config.h>
354359Sroberto#endif
454359Sroberto
554359Sroberto#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_VARITEXT)
654359Sroberto/*
7182007Sroberto * /src/NTP/ntp4-dev/libparse/clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A
8182007Sroberto *
9182007Sroberto * clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A
10182007Sroberto *
11182007Sroberto * Varitext code variant by A.McConnell 1997/01/19
12282408Scy *
1354359Sroberto * Supports Varitext's Radio Clock
14282408Scy *
1554359Sroberto * Used the Meinberg/Computime clock as a template for Varitext Radio Clock
1654359Sroberto *
17182007Sroberto * Codebase:
18182007Sroberto * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
19282408Scy * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
20182007Sroberto *
21182007Sroberto * Redistribution and use in source and binary forms, with or without
22182007Sroberto * modification, are permitted provided that the following conditions
23182007Sroberto * are met:
24182007Sroberto * 1. Redistributions of source code must retain the above copyright
25182007Sroberto *    notice, this list of conditions and the following disclaimer.
26182007Sroberto * 2. Redistributions in binary form must reproduce the above copyright
27182007Sroberto *    notice, this list of conditions and the following disclaimer in the
28182007Sroberto *    documentation and/or other materials provided with the distribution.
29182007Sroberto * 3. Neither the name of the author nor the names of its contributors
30182007Sroberto *    may be used to endorse or promote products derived from this software
31182007Sroberto *    without specific prior written permission.
32182007Sroberto *
33182007Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
34182007Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35182007Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36182007Sroberto * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
37182007Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38182007Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39182007Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40182007Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41182007Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42182007Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43182007Sroberto * SUCH DAMAGE.
44182007Sroberto *
4554359Sroberto */
4654359Sroberto
4754359Sroberto#include "ntp_fp.h"
4854359Sroberto#include "ntp_unixtime.h"
4954359Sroberto#include "ntp_calendar.h"
5054359Sroberto
5154359Sroberto#include "parse.h"
5254359Sroberto
5354359Sroberto#ifndef PARSESTREAM
5482498Sroberto# include "ntp_stdlib.h"
5582498Sroberto# include <stdio.h>
5654359Sroberto#else
5782498Sroberto# include "sys/parsestreams.h"
58280849Scyextern int printf (const char *, ...);
5954359Sroberto#endif
6054359Sroberto
61293423Sdelphij/* static const u_char VT_INITIALISED      = 0x01; */
62293423Sdelphij/* static const u_char VT_SYNCHRONISED     = 0x02; */
63293423Sdelphij/* static const u_char VT_ALARM_STATE      = 0x04; */
6454359Srobertostatic const u_char VT_BST              = 0x08;
65293423Sdelphij/* static const u_char VT_SEASON_CHANGE    = 0x10; */
66293423Sdelphij/* static const u_char VT_LAST_TELEGRAM_OK = 0x20; */
6754359Sroberto
6854359Sroberto/*
6954359Sroberto * The Varitext receiver sends a datagram in the following format every minute
70282408Scy *
71282408Scy * Timestamp	T:YY:MM:MD:WD:HH:MM:SSCRLFSTXXX
7254359Sroberto * Pos          0123456789012345678901 2 3 4567
7354359Sroberto *              0000000000111111111122 2 2 2222
74282408Scy * Parse        T:  :  :  :  :  :  :  \r\n
75282408Scy *
76282408Scy * T	Startcharacter "T" specifies start of the timestamp
77282408Scy * YY	Year MM	Month 1-12
78282408Scy * MD	Day of the month
79282408Scy * WD	Day of week
80282408Scy * HH	Hour
81282408Scy * MM	Minute
82282408Scy * SS	Second
83282408Scy * CR	Carriage return
84282408Scy * LF	Linefeed
8554359Sroberto * ST	Status character
8654359Sroberto *	Bit 0 - Set= Initialised; Reset=Time Invalid (DO NOT USE)
87282408Scy *	Bit 1 - Set= Synchronised; Reset= Unsynchronised
88282408Scy *	Bit 2 - Set= Alarm state; Reset= No alarm
89282408Scy *	Bit 3 - Set= BST; Reset= GMT
90282408Scy *	Bit 4 - Set= Seasonal change in approx hour; Reset= No seasonal change expected
9154359Sroberto *	Bit 5 - Set= Last MSF telegram was OK; Reset= Last telegram was in error;
92282408Scy *	Bit 6 - Always set
9354359Sroberto *	Bit 7 - Unused
94282408Scy * XXX	Checksum calculated using Fletcher's method (ignored for now).
9554359Sroberto */
9654359Sroberto
9754359Srobertostatic struct format varitext_fmt =
9854359Sroberto{
9954359Sroberto  {
10054359Sroberto    {8, 2},  {5,  2}, {2,  2},	/* day, month, year */
10154359Sroberto    {14, 2}, {17, 2}, {20, 2},	/* hour, minute, second */
10254359Sroberto    {11, 2}, {24, 1}		/* dayofweek, status */
10354359Sroberto  },
10454359Sroberto  (const unsigned char*)"T:  :  :  :  :  :  :  \r\n    ",
10554359Sroberto  0
10654359Sroberto};
10754359Sroberto
108282408Scystatic parse_cvt_fnc_t cvt_varitext;
109282408Scystatic parse_inp_fnc_t inp_varitext;
11054359Sroberto
11154359Srobertostruct varitext {
11254359Sroberto  unsigned char start_found;
11354359Sroberto  unsigned char end_found;
11454359Sroberto  unsigned char end_count;
11554359Sroberto  unsigned char previous_ch;
11654359Sroberto  timestamp_t   tstamp;
11754359Sroberto};
11854359Sroberto
11954359Srobertoclockformat_t   clock_varitext =
12054359Sroberto{
12154359Sroberto  inp_varitext,			/* Because of the strange format we need to parse it ourselves */
12254359Sroberto  cvt_varitext,			/* Varitext conversion */
12354359Sroberto  0,				/* no PPS monitoring */
12454359Sroberto  (void *)&varitext_fmt,	/* conversion configuration */
12554359Sroberto  "Varitext Radio Clock",	/* Varitext Radio Clock */
12654359Sroberto  30,				/* string buffer */
12754359Sroberto  sizeof(struct varitext),	/* Private data size required to hold current parse state */
12854359Sroberto};
12954359Sroberto
13054359Sroberto/*
131282408Scy * parse_cvt_fnc_t cvt_varitext
132282408Scy *
13354359Sroberto * convert simple type format
13454359Sroberto */
135282408Scystatic u_long
13654359Srobertocvt_varitext(
13754359Sroberto	     unsigned char	*buffer,
13854359Sroberto	     int    		size,
13954359Sroberto	     struct format	*format,
14054359Sroberto	     clocktime_t	*clock_time,
14154359Sroberto	     void		*local
14254359Sroberto	     )
14354359Sroberto{
14454359Sroberto
145282408Scy  if (!Strok(buffer, format->fixed_string)) {
14654359Sroberto    return CVT_NONE;
14754359Sroberto  } else {
14854359Sroberto    if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day,
14954359Sroberto	     format->field_offsets[O_DAY].length) ||
15054359Sroberto	Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month,
15154359Sroberto	     format->field_offsets[O_MONTH].length) ||
15254359Sroberto	Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year,
15354359Sroberto	     format->field_offsets[O_YEAR].length) ||
15454359Sroberto	Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour,
15554359Sroberto	     format->field_offsets[O_HOUR].length) ||
15654359Sroberto	Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute,
15754359Sroberto	     format->field_offsets[O_MIN].length) ||
15854359Sroberto	Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second,
159282408Scy	     format->field_offsets[O_SEC].length)) {
16054359Sroberto      return CVT_FAIL | CVT_BADFMT;
16154359Sroberto    } else {
16254359Sroberto      u_char *f = (u_char*) &buffer[format->field_offsets[O_FLAGS].offset];
16354359Sroberto
16454359Sroberto      clock_time->flags = 0;
16554359Sroberto      clock_time->utcoffset = 0;
16654359Sroberto
16754359Sroberto      if (((*f) & VT_BST))	/* BST flag is set so set to indicate daylight saving time is active and utc offset */
16854359Sroberto	{
16954359Sroberto	  clock_time->utcoffset = -1*60*60;
17054359Sroberto	  clock_time->flags |= PARSEB_DST;
17154359Sroberto	}
17254359Sroberto      /*
173282408Scy	 if (!((*f) & VT_INITIALISED))  Clock not initialised
17454359Sroberto	 clock_time->flags |= PARSEB_POWERUP;
175282408Scy
176282408Scy	 if (!((*f) & VT_SYNCHRONISED))   Clock not synchronised
17754359Sroberto	 clock_time->flags |= PARSEB_NOSYNC;
178282408Scy
179282408Scy	 if (((*f) & VT_SEASON_CHANGE))  Seasonal change expected in the next hour
18054359Sroberto	 clock_time->flags |= PARSEB_ANNOUNCE;
18154359Sroberto	 */
182282408Scy      return CVT_OK;
18354359Sroberto    }
18454359Sroberto  }
18554359Sroberto}
18654359Sroberto
187282408Scy/* parse_inp_fnc_t inp_varitext */
188282408Scystatic u_long
18954359Srobertoinp_varitext(
19054359Sroberto	     parse_t	 *parseio,
191282408Scy	     char ch,
19254359Sroberto	     timestamp_t *tstamp
19354359Sroberto	     )
19454359Sroberto{
19554359Sroberto  struct varitext *t = (struct varitext *)parseio->parse_pdata;
19654359Sroberto  int    rtc;
19754359Sroberto
198293423Sdelphij  parseprintf(DD_PARSE, ("inp_varitext(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
19954359Sroberto
200282408Scy  if (!t)
20154359Sroberto    return PARSE_INP_SKIP;	/* local data not allocated - sigh! */
20254359Sroberto
203282408Scy  if (ch == 'T')
20454359Sroberto    t->tstamp = *tstamp;
20554359Sroberto
20654359Sroberto  if ((t->previous_ch == 'T') && (ch == ':'))
20754359Sroberto    {
20854359Sroberto      parseprintf(DD_PARSE, ("inp_varitext: START seen\n"));
20954359Sroberto
21054359Sroberto      parseio->parse_data[0] = 'T';
21154359Sroberto      parseio->parse_index=1;
21254359Sroberto      parseio->parse_dtime.parse_stime = t->tstamp; /* Time stamp at packet start */
21354359Sroberto      t->start_found = 1;
21454359Sroberto      t->end_found = 0;
21554359Sroberto      t->end_count = 0;
21654359Sroberto    }
21754359Sroberto
21854359Sroberto  if (t->start_found)
21954359Sroberto    {
22054359Sroberto      if ((rtc = parse_addchar(parseio, ch)) != PARSE_INP_SKIP)
22154359Sroberto	{
22254359Sroberto	  parseprintf(DD_PARSE, ("inp_varitext: ABORTED due to too many characters\n"));
22354359Sroberto
22454359Sroberto	  memset(t, 0, sizeof(struct varitext));
22554359Sroberto	  return rtc;
22654359Sroberto	}
22754359Sroberto
228282408Scy      if (t->end_found)
22954359Sroberto	{
23054359Sroberto	  if (++(t->end_count) == 4) /* Finally found the end of the message */
23154359Sroberto	    {
23254359Sroberto	      parseprintf(DD_PARSE, ("inp_varitext: END seen\n"));
23354359Sroberto
23454359Sroberto	      memset(t, 0, sizeof(struct varitext));
23554359Sroberto	      if ((rtc = parse_addchar(parseio, 0)) == PARSE_INP_SKIP)
23654359Sroberto		return parse_end(parseio);
23754359Sroberto	      else
23854359Sroberto		return rtc;
239282408Scy	    }
24054359Sroberto	}
24154359Sroberto
242282408Scy      if ((t->previous_ch == '\r') && (ch == '\n'))
24354359Sroberto	{
24454359Sroberto	  t->end_found = 1;
24554359Sroberto	}
24654359Sroberto
24754359Sroberto    }
248282408Scy
24954359Sroberto  t->previous_ch = ch;
25054359Sroberto
25154359Sroberto  return PARSE_INP_SKIP;
25254359Sroberto}
25354359Sroberto
25454359Sroberto#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */
25554359Srobertoint clk_varitext_bs;
25654359Sroberto#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */
25754359Sroberto
25854359Sroberto/*
259182007Sroberto * History:
260182007Sroberto *
261182007Sroberto * clk_varitext.c,v
262182007Sroberto * Revision 1.5  2005/04/16 17:32:10  kardel
263182007Sroberto * update copyright
264182007Sroberto *
265182007Sroberto * Revision 1.4  2004/11/14 15:29:41  kardel
266182007Sroberto * support PPSAPI, upgrade Copyright to Berkeley style
267182007Sroberto *
268182007Sroberto *
26954359Sroberto * Revision 1.0  1997/06/02 13:16:30  McConnell
27054359Sroberto * File created
27154359Sroberto *
27254359Sroberto */
273