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