xref: /netbsd-src/external/bsd/ntp/dist/libparse/clk_schmid.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: clk_schmid.c,v 1.7 2024/08/18 20:47:17 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * /src/NTP/ntp4-dev/libparse/clk_schmid.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A
5abb0f93cSkardel  *
6abb0f93cSkardel  * clk_schmid.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A
7abb0f93cSkardel  *
8abb0f93cSkardel  * Schmid clock support
9abb0f93cSkardel  * based on information and testing from Adam W. Feigin et. al (Swisstime iis.ethz.ch)
10abb0f93cSkardel  *
115d681e99Schristos  * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
127476e6e4Schristos  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
13abb0f93cSkardel  *
14abb0f93cSkardel  * Redistribution and use in source and binary forms, with or without
15abb0f93cSkardel  * modification, are permitted provided that the following conditions
16abb0f93cSkardel  * are met:
17abb0f93cSkardel  * 1. Redistributions of source code must retain the above copyright
18abb0f93cSkardel  *    notice, this list of conditions and the following disclaimer.
19abb0f93cSkardel  * 2. Redistributions in binary form must reproduce the above copyright
20abb0f93cSkardel  *    notice, this list of conditions and the following disclaimer in the
21abb0f93cSkardel  *    documentation and/or other materials provided with the distribution.
22abb0f93cSkardel  * 3. Neither the name of the author nor the names of its contributors
23abb0f93cSkardel  *    may be used to endorse or promote products derived from this software
24abb0f93cSkardel  *    without specific prior written permission.
25abb0f93cSkardel  *
26abb0f93cSkardel  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27abb0f93cSkardel  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28abb0f93cSkardel  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29abb0f93cSkardel  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30abb0f93cSkardel  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31abb0f93cSkardel  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32abb0f93cSkardel  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33abb0f93cSkardel  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34abb0f93cSkardel  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35abb0f93cSkardel  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36abb0f93cSkardel  * SUCH DAMAGE.
37abb0f93cSkardel  *
38abb0f93cSkardel  */
39abb0f93cSkardel 
40abb0f93cSkardel #if HAVE_CONFIG_H
41abb0f93cSkardel # include <config.h>
42abb0f93cSkardel #endif
43abb0f93cSkardel 
44abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID)
45abb0f93cSkardel 
46abb0f93cSkardel #include "ntp_fp.h"
47abb0f93cSkardel #include "ntp_unixtime.h"
48abb0f93cSkardel #include "ntp_calendar.h"
49abb0f93cSkardel 
50abb0f93cSkardel #include "parse.h"
51abb0f93cSkardel 
52abb0f93cSkardel #ifndef PARSESTREAM
53abb0f93cSkardel #include "ntp_stdlib.h"
54abb0f93cSkardel #include <stdio.h>
55abb0f93cSkardel #else
56abb0f93cSkardel #include "sys/parsestreams.h"
57abb0f93cSkardel extern int printf (const char *, ...);
58abb0f93cSkardel #endif
59abb0f93cSkardel 
60abb0f93cSkardel /*
61abb0f93cSkardel  * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch)
62abb0f93cSkardel  *
63abb0f93cSkardel  * The command to Schmid's DCF77 clock is a single byte; each bit
64abb0f93cSkardel  * allows the user to select some part of the time string, as follows (the
65abb0f93cSkardel  * output for the lsb is sent first).
66abb0f93cSkardel  *
67abb0f93cSkardel  * Bit 0:	time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths
68abb0f93cSkardel  * Bit 1:	date 3 bytes *binary, not BCD: dd.mm.yy
69abb0f93cSkardel  * Bit 2:	week day, 1 byte (unused here)
70abb0f93cSkardel  * Bit 3:	time zone, 1 byte, 0=MET, 1=MEST. (unused here)
71abb0f93cSkardel  * Bit 4:	clock status, 1 byte,	0=time invalid,
72abb0f93cSkardel  *					1=time from crystal backup,
73abb0f93cSkardel  *					3=time from DCF77
74abb0f93cSkardel  * Bit 5:	transmitter status, 1 byte,
75abb0f93cSkardel  *					bit 0: backup antenna
76abb0f93cSkardel  *					bit 1: time zone change within 1h
77abb0f93cSkardel  *					bit 3,2: TZ 01=MEST, 10=MET
78abb0f93cSkardel  *					bit 4: leap second will be
79abb0f93cSkardel  *						added within one hour
80abb0f93cSkardel  *					bits 5-7: Zero
81abb0f93cSkardel  * Bit 6:	time in backup mode, units of 5 minutes (unused here)
82abb0f93cSkardel  *
83abb0f93cSkardel  */
84abb0f93cSkardel #define WS_TIME		0x01
85abb0f93cSkardel #define WS_SIGNAL	0x02
86abb0f93cSkardel 
877476e6e4Schristos #define WS_CALLBIT	0x01  /* "call bit" used to signalize irregularities in the control facilities */
88abb0f93cSkardel #define WS_ANNOUNCE	0x02
89abb0f93cSkardel #define WS_TZ		0x0c
90abb0f93cSkardel #define   WS_MET	0x08
91abb0f93cSkardel #define   WS_MEST	0x04
92abb0f93cSkardel #define WS_LEAP		0x10
93abb0f93cSkardel 
947476e6e4Schristos static parse_cvt_fnc_t cvt_schmid;
957476e6e4Schristos static parse_inp_fnc_t inp_schmid;
96abb0f93cSkardel 
97abb0f93cSkardel clockformat_t clock_schmid =
98abb0f93cSkardel {
99abb0f93cSkardel   inp_schmid,			/* no input handling */
100abb0f93cSkardel   cvt_schmid,			/* Schmid conversion */
101abb0f93cSkardel   0,				/* not direct PPS monitoring */
102abb0f93cSkardel   0,				/* conversion configuration */
103abb0f93cSkardel   "Schmid",			/* Schmid receiver */
104abb0f93cSkardel   12,				/* binary data buffer */
105abb0f93cSkardel   0,				/* no private data (complete messages) */
106abb0f93cSkardel };
107abb0f93cSkardel 
1087476e6e4Schristos /* parse_cvt_fnc_t */
109abb0f93cSkardel static u_long
110abb0f93cSkardel cvt_schmid(
111abb0f93cSkardel 	   unsigned char *buffer,
112abb0f93cSkardel 	   int            size,
113abb0f93cSkardel 	   struct format *format,
114abb0f93cSkardel 	   clocktime_t   *clock_time,
115abb0f93cSkardel 	   void          *local
116abb0f93cSkardel 	)
117abb0f93cSkardel {
118abb0f93cSkardel 	if ((size != 11) || (buffer[10] != (unsigned char)'\375'))
119abb0f93cSkardel 	{
120abb0f93cSkardel 		return CVT_NONE;
121abb0f93cSkardel 	}
122abb0f93cSkardel 	else
123abb0f93cSkardel 	{
124abb0f93cSkardel 		if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] >  9) /* Time */
125abb0f93cSkardel 		{
126abb0f93cSkardel 			return CVT_FAIL|CVT_BADTIME;
127abb0f93cSkardel 		}
128abb0f93cSkardel 		else
129abb0f93cSkardel 		    if (buffer[4] <  1 || buffer[4] > 31 || buffer[5] <  1 || buffer[5] > 12
130abb0f93cSkardel 			||  buffer[6] > 99)
131abb0f93cSkardel 		    {
132abb0f93cSkardel 			    return CVT_FAIL|CVT_BADDATE;
133abb0f93cSkardel 		    }
134abb0f93cSkardel 		    else
135abb0f93cSkardel 		    {
136abb0f93cSkardel 			    clock_time->hour    = buffer[0];
137abb0f93cSkardel 			    clock_time->minute  = buffer[1];
138abb0f93cSkardel 			    clock_time->second  = buffer[2];
139abb0f93cSkardel 			    clock_time->usecond = buffer[3] * 100000;
140abb0f93cSkardel 			    clock_time->day     = buffer[4];
141abb0f93cSkardel 			    clock_time->month   = buffer[5];
142abb0f93cSkardel 			    clock_time->year    = buffer[6];
143abb0f93cSkardel 
144abb0f93cSkardel 			    clock_time->flags   = 0;
145abb0f93cSkardel 
146abb0f93cSkardel 			    switch (buffer[8] & WS_TZ)
147abb0f93cSkardel 			    {
148abb0f93cSkardel 				case WS_MET:
149abb0f93cSkardel 				    clock_time->utcoffset = -1*60*60;
150abb0f93cSkardel 				    break;
151abb0f93cSkardel 
152abb0f93cSkardel 				case WS_MEST:
153abb0f93cSkardel 				    clock_time->utcoffset = -2*60*60;
154abb0f93cSkardel 				    clock_time->flags    |= PARSEB_DST;
155abb0f93cSkardel 				    break;
156abb0f93cSkardel 
157abb0f93cSkardel 				default:
158abb0f93cSkardel 				    return CVT_FAIL|CVT_BADFMT;
159abb0f93cSkardel 			    }
160abb0f93cSkardel 
161abb0f93cSkardel 			    if (!(buffer[7] & WS_TIME))
162abb0f93cSkardel 			    {
163abb0f93cSkardel 				    clock_time->flags |= PARSEB_POWERUP;
164abb0f93cSkardel 			    }
165abb0f93cSkardel 
166abb0f93cSkardel 			    if (!(buffer[7] & WS_SIGNAL))
167abb0f93cSkardel 			    {
168abb0f93cSkardel 				    clock_time->flags |= PARSEB_NOSYNC;
169abb0f93cSkardel 			    }
170abb0f93cSkardel 
171abb0f93cSkardel 			    if (buffer[7] & WS_SIGNAL)
172abb0f93cSkardel 			    {
1737476e6e4Schristos 				    if (buffer[8] & WS_CALLBIT)
174abb0f93cSkardel 				    {
1757476e6e4Schristos 					    clock_time->flags |= PARSEB_CALLBIT;
176abb0f93cSkardel 				    }
177abb0f93cSkardel 
178abb0f93cSkardel 				    if (buffer[8] & WS_ANNOUNCE)
179abb0f93cSkardel 				    {
180abb0f93cSkardel 					    clock_time->flags |= PARSEB_ANNOUNCE;
181abb0f93cSkardel 				    }
182abb0f93cSkardel 
183abb0f93cSkardel 				    if (buffer[8] & WS_LEAP)
184abb0f93cSkardel 				    {
185abb0f93cSkardel 					    clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */
186abb0f93cSkardel 				    }
187abb0f93cSkardel 			    }
188abb0f93cSkardel 
1895d681e99Schristos 			    clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_CALLBIT;
190abb0f93cSkardel 
191abb0f93cSkardel 			    return CVT_OK;
192abb0f93cSkardel 		    }
193abb0f93cSkardel 	}
194abb0f93cSkardel }
195abb0f93cSkardel 
196abb0f93cSkardel /*
1977476e6e4Schristos  * parse_inp_fnc_t inp_schmid
198abb0f93cSkardel  *
1997476e6e4Schristos  * grab data from input stream
200abb0f93cSkardel  */
201abb0f93cSkardel static u_long
202abb0f93cSkardel inp_schmid(
203abb0f93cSkardel 	  parse_t      *parseio,
2047476e6e4Schristos 	  char         ch,
205abb0f93cSkardel 	  timestamp_t  *tstamp
206abb0f93cSkardel 	  )
207abb0f93cSkardel {
208abb0f93cSkardel 	unsigned int rtc;
209abb0f93cSkardel 
2108b8da087Schristos 	parseprintf(DD_PARSE, ("inp_schmid(0x%p, 0x%x, ...)\n", (void*)parseio, ch));
211abb0f93cSkardel 
2127476e6e4Schristos 	switch ((uint8_t)ch)
213abb0f93cSkardel 	{
214abb0f93cSkardel 	case 0xFD:		/*  */
2157476e6e4Schristos 		parseprintf(DD_PARSE, ("inp_schmid: 0xFD seen\n"));
216abb0f93cSkardel 		if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP)
217abb0f93cSkardel 			return parse_end(parseio);
218abb0f93cSkardel 		else
219abb0f93cSkardel 			return rtc;
220abb0f93cSkardel 
221abb0f93cSkardel 	default:
222abb0f93cSkardel 		return parse_addchar(parseio, ch);
223abb0f93cSkardel 	}
224abb0f93cSkardel }
225abb0f93cSkardel 
226abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */
227*eabc0478Schristos NONEMPTY_TRANSLATION_UNIT
228abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */
229abb0f93cSkardel 
230abb0f93cSkardel /*
231abb0f93cSkardel  * History:
232abb0f93cSkardel  *
233abb0f93cSkardel  * clk_schmid.c,v
234abb0f93cSkardel  * Revision 4.9  2005/04/16 17:32:10  kardel
235abb0f93cSkardel  * update copyright
236abb0f93cSkardel  *
237abb0f93cSkardel  * Revision 4.8  2004/11/14 15:29:41  kardel
238abb0f93cSkardel  * support PPSAPI, upgrade Copyright to Berkeley style
239abb0f93cSkardel  *
240abb0f93cSkardel  * Revision 4.5  1999/11/28 09:13:51  kardel
241abb0f93cSkardel  * RECON_4_0_98F
242abb0f93cSkardel  *
243abb0f93cSkardel  * Revision 4.4  1998/06/13 12:06:03  kardel
244abb0f93cSkardel  * fix SYSV clock name clash
245abb0f93cSkardel  *
246abb0f93cSkardel  * Revision 4.3  1998/06/12 15:22:29  kardel
247abb0f93cSkardel  * fix prototypes
248abb0f93cSkardel  *
249abb0f93cSkardel  * Revision 4.2  1998/06/12 09:13:26  kardel
250abb0f93cSkardel  * conditional compile macros fixed
251abb0f93cSkardel  * printf prototype
252abb0f93cSkardel  *
253abb0f93cSkardel  * Revision 4.1  1998/05/24 09:39:53  kardel
254abb0f93cSkardel  * implementation of the new IO handling model
255abb0f93cSkardel  *
256abb0f93cSkardel  * Revision 4.0  1998/04/10 19:45:31  kardel
257abb0f93cSkardel  * Start 4.0 release version numbering
258abb0f93cSkardel  *
259abb0f93cSkardel  * from V3 3.22 log info deleted 1998/04/11 kardel
260abb0f93cSkardel  */
261