1*eabc0478Schristos /* $NetBSD: clk_varitext.c,v 1.7 2024/08/18 20:47:17 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel #ifdef HAVE_CONFIG_H 4abb0f93cSkardel # include <config.h> 5abb0f93cSkardel #endif 6abb0f93cSkardel 7abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_VARITEXT) 8abb0f93cSkardel /* 9abb0f93cSkardel * /src/NTP/ntp4-dev/libparse/clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A 10abb0f93cSkardel * 11abb0f93cSkardel * clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A 12abb0f93cSkardel * 13abb0f93cSkardel * Varitext code variant by A.McConnell 1997/01/19 14abb0f93cSkardel * 15abb0f93cSkardel * Supports Varitext's Radio Clock 16abb0f93cSkardel * 17abb0f93cSkardel * Used the Meinberg/Computime clock as a template for Varitext Radio Clock 18abb0f93cSkardel * 19abb0f93cSkardel * Codebase: 20abb0f93cSkardel * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> 217476e6e4Schristos * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 22abb0f93cSkardel * 23abb0f93cSkardel * Redistribution and use in source and binary forms, with or without 24abb0f93cSkardel * modification, are permitted provided that the following conditions 25abb0f93cSkardel * are met: 26abb0f93cSkardel * 1. Redistributions of source code must retain the above copyright 27abb0f93cSkardel * notice, this list of conditions and the following disclaimer. 28abb0f93cSkardel * 2. Redistributions in binary form must reproduce the above copyright 29abb0f93cSkardel * notice, this list of conditions and the following disclaimer in the 30abb0f93cSkardel * documentation and/or other materials provided with the distribution. 31abb0f93cSkardel * 3. Neither the name of the author nor the names of its contributors 32abb0f93cSkardel * may be used to endorse or promote products derived from this software 33abb0f93cSkardel * without specific prior written permission. 34abb0f93cSkardel * 35abb0f93cSkardel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 36abb0f93cSkardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37abb0f93cSkardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38abb0f93cSkardel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 39abb0f93cSkardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40abb0f93cSkardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41abb0f93cSkardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42abb0f93cSkardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43abb0f93cSkardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44abb0f93cSkardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45abb0f93cSkardel * SUCH DAMAGE. 46abb0f93cSkardel * 47abb0f93cSkardel */ 48abb0f93cSkardel 49abb0f93cSkardel #include "ntp_fp.h" 50abb0f93cSkardel #include "ntp_unixtime.h" 51abb0f93cSkardel #include "ntp_calendar.h" 52abb0f93cSkardel 53abb0f93cSkardel #include "parse.h" 54abb0f93cSkardel 55abb0f93cSkardel #ifndef PARSESTREAM 56abb0f93cSkardel # include "ntp_stdlib.h" 57abb0f93cSkardel # include <stdio.h> 58abb0f93cSkardel #else 59abb0f93cSkardel # include "sys/parsestreams.h" 60abb0f93cSkardel extern int printf (const char *, ...); 61abb0f93cSkardel #endif 62abb0f93cSkardel 638b8da087Schristos /* static const u_char VT_INITIALISED = 0x01; */ 648b8da087Schristos /* static const u_char VT_SYNCHRONISED = 0x02; */ 658b8da087Schristos /* static const u_char VT_ALARM_STATE = 0x04; */ 66abb0f93cSkardel static const u_char VT_BST = 0x08; 678b8da087Schristos /* static const u_char VT_SEASON_CHANGE = 0x10; */ 688b8da087Schristos /* static const u_char VT_LAST_TELEGRAM_OK = 0x20; */ 69abb0f93cSkardel 70abb0f93cSkardel /* 71abb0f93cSkardel * The Varitext receiver sends a datagram in the following format every minute 72abb0f93cSkardel * 73abb0f93cSkardel * Timestamp T:YY:MM:MD:WD:HH:MM:SSCRLFSTXXX 74abb0f93cSkardel * Pos 0123456789012345678901 2 3 4567 75abb0f93cSkardel * 0000000000111111111122 2 2 2222 76abb0f93cSkardel * Parse T: : : : : : : \r\n 77abb0f93cSkardel * 78abb0f93cSkardel * T Startcharacter "T" specifies start of the timestamp 79abb0f93cSkardel * YY Year MM Month 1-12 80abb0f93cSkardel * MD Day of the month 81abb0f93cSkardel * WD Day of week 82abb0f93cSkardel * HH Hour 83abb0f93cSkardel * MM Minute 84abb0f93cSkardel * SS Second 85abb0f93cSkardel * CR Carriage return 86abb0f93cSkardel * LF Linefeed 87abb0f93cSkardel * ST Status character 88abb0f93cSkardel * Bit 0 - Set= Initialised; Reset=Time Invalid (DO NOT USE) 89abb0f93cSkardel * Bit 1 - Set= Synchronised; Reset= Unsynchronised 90abb0f93cSkardel * Bit 2 - Set= Alarm state; Reset= No alarm 91abb0f93cSkardel * Bit 3 - Set= BST; Reset= GMT 92abb0f93cSkardel * Bit 4 - Set= Seasonal change in approx hour; Reset= No seasonal change expected 93abb0f93cSkardel * Bit 5 - Set= Last MSF telegram was OK; Reset= Last telegram was in error; 94abb0f93cSkardel * Bit 6 - Always set 95abb0f93cSkardel * Bit 7 - Unused 96abb0f93cSkardel * XXX Checksum calculated using Fletcher's method (ignored for now). 97abb0f93cSkardel */ 98abb0f93cSkardel 99abb0f93cSkardel static struct format varitext_fmt = 100abb0f93cSkardel { 101abb0f93cSkardel { 102abb0f93cSkardel {8, 2}, {5, 2}, {2, 2}, /* day, month, year */ 103abb0f93cSkardel {14, 2}, {17, 2}, {20, 2}, /* hour, minute, second */ 104abb0f93cSkardel {11, 2}, {24, 1} /* dayofweek, status */ 105abb0f93cSkardel }, 106abb0f93cSkardel (const unsigned char*)"T: : : : : : : \r\n ", 107abb0f93cSkardel 0 108abb0f93cSkardel }; 109abb0f93cSkardel 1107476e6e4Schristos static parse_cvt_fnc_t cvt_varitext; 1117476e6e4Schristos static parse_inp_fnc_t inp_varitext; 112abb0f93cSkardel 113abb0f93cSkardel struct varitext { 114abb0f93cSkardel unsigned char start_found; 115abb0f93cSkardel unsigned char end_found; 116abb0f93cSkardel unsigned char end_count; 117abb0f93cSkardel unsigned char previous_ch; 118abb0f93cSkardel timestamp_t tstamp; 119abb0f93cSkardel }; 120abb0f93cSkardel 121abb0f93cSkardel clockformat_t clock_varitext = 122abb0f93cSkardel { 123abb0f93cSkardel inp_varitext, /* Because of the strange format we need to parse it ourselves */ 124abb0f93cSkardel cvt_varitext, /* Varitext conversion */ 125abb0f93cSkardel 0, /* no PPS monitoring */ 126abb0f93cSkardel (void *)&varitext_fmt, /* conversion configuration */ 127abb0f93cSkardel "Varitext Radio Clock", /* Varitext Radio Clock */ 128abb0f93cSkardel 30, /* string buffer */ 129abb0f93cSkardel sizeof(struct varitext), /* Private data size required to hold current parse state */ 130abb0f93cSkardel }; 131abb0f93cSkardel 132abb0f93cSkardel /* 1337476e6e4Schristos * parse_cvt_fnc_t cvt_varitext 134abb0f93cSkardel * 135abb0f93cSkardel * convert simple type format 136abb0f93cSkardel */ 137abb0f93cSkardel static u_long 138abb0f93cSkardel cvt_varitext( 139abb0f93cSkardel unsigned char *buffer, 140abb0f93cSkardel int size, 141abb0f93cSkardel struct format *format, 142abb0f93cSkardel clocktime_t *clock_time, 143abb0f93cSkardel void *local 144abb0f93cSkardel ) 145abb0f93cSkardel { 146abb0f93cSkardel 147abb0f93cSkardel if (!Strok(buffer, format->fixed_string)) { 148abb0f93cSkardel return CVT_NONE; 149abb0f93cSkardel } else { 150abb0f93cSkardel if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, 151abb0f93cSkardel format->field_offsets[O_DAY].length) || 152abb0f93cSkardel Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, 153abb0f93cSkardel format->field_offsets[O_MONTH].length) || 154abb0f93cSkardel Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, 155abb0f93cSkardel format->field_offsets[O_YEAR].length) || 156abb0f93cSkardel Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, 157abb0f93cSkardel format->field_offsets[O_HOUR].length) || 158abb0f93cSkardel Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, 159abb0f93cSkardel format->field_offsets[O_MIN].length) || 160abb0f93cSkardel Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, 161abb0f93cSkardel format->field_offsets[O_SEC].length)) { 162abb0f93cSkardel return CVT_FAIL | CVT_BADFMT; 163abb0f93cSkardel } else { 164abb0f93cSkardel u_char *f = (u_char*) &buffer[format->field_offsets[O_FLAGS].offset]; 165abb0f93cSkardel 166abb0f93cSkardel clock_time->flags = 0; 167abb0f93cSkardel clock_time->utcoffset = 0; 168abb0f93cSkardel 169abb0f93cSkardel if (((*f) & VT_BST)) /* BST flag is set so set to indicate daylight saving time is active and utc offset */ 170abb0f93cSkardel { 171abb0f93cSkardel clock_time->utcoffset = -1*60*60; 172abb0f93cSkardel clock_time->flags |= PARSEB_DST; 173abb0f93cSkardel } 174abb0f93cSkardel /* 175abb0f93cSkardel if (!((*f) & VT_INITIALISED)) Clock not initialised 176abb0f93cSkardel clock_time->flags |= PARSEB_POWERUP; 177abb0f93cSkardel 178abb0f93cSkardel if (!((*f) & VT_SYNCHRONISED)) Clock not synchronised 179abb0f93cSkardel clock_time->flags |= PARSEB_NOSYNC; 180abb0f93cSkardel 181abb0f93cSkardel if (((*f) & VT_SEASON_CHANGE)) Seasonal change expected in the next hour 182abb0f93cSkardel clock_time->flags |= PARSEB_ANNOUNCE; 183abb0f93cSkardel */ 184abb0f93cSkardel return CVT_OK; 185abb0f93cSkardel } 186abb0f93cSkardel } 187abb0f93cSkardel } 188abb0f93cSkardel 1897476e6e4Schristos /* parse_inp_fnc_t inp_varitext */ 190abb0f93cSkardel static u_long 191abb0f93cSkardel inp_varitext( 192abb0f93cSkardel parse_t *parseio, 1937476e6e4Schristos char ch, 194abb0f93cSkardel timestamp_t *tstamp 195abb0f93cSkardel ) 196abb0f93cSkardel { 197abb0f93cSkardel struct varitext *t = (struct varitext *)parseio->parse_pdata; 198abb0f93cSkardel int rtc; 199abb0f93cSkardel 2008b8da087Schristos parseprintf(DD_PARSE, ("inp_varitext(0x%p, 0x%x, ...)\n", (void*)parseio, ch)); 201abb0f93cSkardel 202abb0f93cSkardel if (!t) 203abb0f93cSkardel return PARSE_INP_SKIP; /* local data not allocated - sigh! */ 204abb0f93cSkardel 205abb0f93cSkardel if (ch == 'T') 206abb0f93cSkardel t->tstamp = *tstamp; 207abb0f93cSkardel 208abb0f93cSkardel if ((t->previous_ch == 'T') && (ch == ':')) 209abb0f93cSkardel { 210abb0f93cSkardel parseprintf(DD_PARSE, ("inp_varitext: START seen\n")); 211abb0f93cSkardel 212abb0f93cSkardel parseio->parse_data[0] = 'T'; 213abb0f93cSkardel parseio->parse_index=1; 214abb0f93cSkardel parseio->parse_dtime.parse_stime = t->tstamp; /* Time stamp at packet start */ 215abb0f93cSkardel t->start_found = 1; 216abb0f93cSkardel t->end_found = 0; 217abb0f93cSkardel t->end_count = 0; 218abb0f93cSkardel } 219abb0f93cSkardel 220abb0f93cSkardel if (t->start_found) 221abb0f93cSkardel { 222abb0f93cSkardel if ((rtc = parse_addchar(parseio, ch)) != PARSE_INP_SKIP) 223abb0f93cSkardel { 224abb0f93cSkardel parseprintf(DD_PARSE, ("inp_varitext: ABORTED due to too many characters\n")); 225abb0f93cSkardel 226abb0f93cSkardel memset(t, 0, sizeof(struct varitext)); 227abb0f93cSkardel return rtc; 228abb0f93cSkardel } 229abb0f93cSkardel 230abb0f93cSkardel if (t->end_found) 231abb0f93cSkardel { 232abb0f93cSkardel if (++(t->end_count) == 4) /* Finally found the end of the message */ 233abb0f93cSkardel { 234abb0f93cSkardel parseprintf(DD_PARSE, ("inp_varitext: END seen\n")); 235abb0f93cSkardel 236abb0f93cSkardel memset(t, 0, sizeof(struct varitext)); 237abb0f93cSkardel if ((rtc = parse_addchar(parseio, 0)) == PARSE_INP_SKIP) 238abb0f93cSkardel return parse_end(parseio); 239abb0f93cSkardel else 240abb0f93cSkardel return rtc; 241abb0f93cSkardel } 242abb0f93cSkardel } 243abb0f93cSkardel 244abb0f93cSkardel if ((t->previous_ch == '\r') && (ch == '\n')) 245abb0f93cSkardel { 246abb0f93cSkardel t->end_found = 1; 247abb0f93cSkardel } 248abb0f93cSkardel 249abb0f93cSkardel } 250abb0f93cSkardel 251abb0f93cSkardel t->previous_ch = ch; 252abb0f93cSkardel 253abb0f93cSkardel return PARSE_INP_SKIP; 254abb0f93cSkardel } 255abb0f93cSkardel 256abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */ 257*eabc0478Schristos NONEMPTY_TRANSLATION_UNIT 258abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */ 259abb0f93cSkardel 260abb0f93cSkardel /* 261abb0f93cSkardel * History: 262abb0f93cSkardel * 263abb0f93cSkardel * clk_varitext.c,v 264abb0f93cSkardel * Revision 1.5 2005/04/16 17:32:10 kardel 265abb0f93cSkardel * update copyright 266abb0f93cSkardel * 267abb0f93cSkardel * Revision 1.4 2004/11/14 15:29:41 kardel 268abb0f93cSkardel * support PPSAPI, upgrade Copyright to Berkeley style 269abb0f93cSkardel * 270abb0f93cSkardel * 271abb0f93cSkardel * Revision 1.0 1997/06/02 13:16:30 McConnell 272abb0f93cSkardel * File created 273abb0f93cSkardel * 274abb0f93cSkardel */ 275