xref: /freebsd/contrib/ntp/ntpd/refclock_jjy.c (revision 4f0a4502a1f33fef287ac558c98e5ef99a32216f)
1 /*
2  * refclock_jjy - clock driver for JJY receivers
3  */
4 
5 /**********************************************************************/
6 /*								      */
7 /*  Copyright (C) 2001-2015, Takao Abe.  All rights reserved.	      */
8 /*								      */
9 /*  Permission to use, copy, modify, and distribute this software     */
10 /*  and its documentation for any purpose is hereby granted	      */
11 /*  without fee, provided that the following conditions are met:      */
12 /*								      */
13 /*  One retains the entire copyright notice properly, and both the    */
14 /*  copyright notice and this license. in the documentation and/or    */
15 /*  other materials provided with the distribution.		      */
16 /*								      */
17 /*  This software and the name of the author must not be used to      */
18 /*  endorse or promote products derived from this software without    */
19 /*  prior written permission.					      */
20 /*								      */
21 /*  THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED    */
22 /*  WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE	      */
23 /*  IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A	      */
24 /*  PARTICULAR PURPOSE.						      */
25 /*  IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT,  */
26 /*  INDIRECT, GENERAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES   */
27 /*  ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE	      */
28 /*  GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS      */
29 /*  INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,     */
30 /*  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING	      */
31 /*  NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF    */
32 /*  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
33 /*								      */
34 /*  This driver is developed in my private time, and is opened as     */
35 /*  voluntary contributions for the NTP.			      */
36 /*  The manufacturer of the JJY receiver has not participated in      */
37 /*  a development of this driver.				      */
38 /*  The manufacturer does not warrant anything about this driver,     */
39 /*  and is not liable for anything about this driver.		      */
40 /*								      */
41 /**********************************************************************/
42 /*								      */
43 /*  Author     Takao Abe					      */
44 /*  Email      takao_abe@xurb.jp				      */
45 /*  Homepage   http://www.bea.hi-ho.ne.jp/abetakao/		      */
46 /*								      */
47 /*  The email address abetakao@bea.hi-ho.ne.jp is never read	      */
48 /*  from 2010, because a few filtering rule are provided by the	      */
49 /*  "hi-ho.ne.jp", and lots of spam mail are reached.		      */
50 /*  New email address for supporting the refclock_jjy is	      */
51 /*  takao_abe@xurb.jp						      */
52 /*								      */
53 /**********************************************************************/
54 /*								      */
55 /*  History							      */
56 /*								      */
57 /*  2001/07/15							      */
58 /*    [New]    Support the Tristate Ltd. JJY receiver		      */
59 /*								      */
60 /*  2001/08/04							      */
61 /*    [Change] Log to clockstats even if bad reply		      */
62 /*    [Fix]    PRECISION = (-3) (about 100 ms)			      */
63 /*    [Add]    Support the C-DEX Co.Ltd. JJY receiver		      */
64 /*								      */
65 /*  2001/12/04							      */
66 /*    [Fix]    C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp )      */
67 /*								      */
68 /*  2002/07/12							      */
69 /*    [Fix]    Portability for FreeBSD ( patched by the user )	      */
70 /*								      */
71 /*  2004/10/31							      */
72 /*    [Change] Command send timing for the Tristate Ltd. JJY receiver */
73 /*	       JJY-01 ( Firmware version 2.01 )			      */
74 /*	       Thanks to Andy Taki for testing under FreeBSD	      */
75 /*								      */
76 /*  2004/11/28							      */
77 /*    [Add]    Support the Echo Keisokuki LT-2000 receiver	      */
78 /*								      */
79 /*  2006/11/04							      */
80 /*    [Fix]    C-DEX JST2000					      */
81 /*	       Thanks to Hideo Kuramatsu for the patch		      */
82 /*								      */
83 /*  2009/04/05							      */
84 /*    [Add]    Support the CITIZEN T.I.C JJY-200 receiver	      */
85 /*								      */
86 /*  2010/11/20							      */
87 /*    [Change] Bug 1618 ( Harmless )				      */
88 /*	       Code clean up ( Remove unreachable codes ) in	      */
89 /*	       jjy_start()					      */
90 /*    [Change] Change clockstats format of the Tristate JJY01/02      */
91 /*	       Issues more command to get the status of the receiver  */
92 /*	       when "fudge 127.127.40.X flag1 1" is specified	      */
93 /*	       ( DATE,STIM -> DCST,STUS,DATE,STIM )		      */
94 /*								      */
95 /*  2011/04/30							      */
96 /*    [Add]    Support the Tristate Ltd. TS-GPSclock-01		      */
97 /*								      */
98 /*  2015/03/29							      */
99 /*    [Add]    Support the Telephone JJY			      */
100 /*    [Change] Split the start up routine into each JJY receivers.    */
101 /*             Change raw data internal bufferring process            */
102 /*             Change over midnight handling of TS-JJY01 and TS-GPS01 */
103 /*             to put DATE command between before and after TIME's.   */
104 /*             Unify the writing clockstats of all JJY receivers.     */
105 /*								      */
106 /*  2015/05/15							      */
107 /*    [Add]    Support the SEIKO TIME SYSTEMS TDC-300		      */
108 /*								      */
109 /**********************************************************************/
110 
111 #ifdef HAVE_CONFIG_H
112 #include <config.h>
113 #endif
114 
115 #if defined(REFCLOCK) && defined(CLOCK_JJY)
116 
117 #include <stdio.h>
118 #include <ctype.h>
119 #include <string.h>
120 #include <sys/time.h>
121 #include <time.h>
122 
123 #include "ntpd.h"
124 #include "ntp_io.h"
125 #include "ntp_tty.h"
126 #include "ntp_refclock.h"
127 #include "ntp_calendar.h"
128 #include "ntp_stdlib.h"
129 
130 /**********************************************************************/
131 
132 /*
133  * Interface definitions
134  */
135 #define	DEVICE  	"/dev/jjy%d"	/* device name and unit */
136 #define	SPEED232_TRISTATE_JJY01		B9600   /* UART speed (9600 baud) */
137 #define	SPEED232_CDEX_JST2000		B9600   /* UART speed (9600 baud) */
138 #define	SPEED232_ECHOKEISOKUKI_LT2000	B9600   /* UART speed (9600 baud) */
139 #define	SPEED232_CITIZENTIC_JJY200	B4800   /* UART speed (4800 baud) */
140 #define	SPEED232_TRISTATE_GPSCLOCK01	B38400  /* USB  speed (38400 baud) */
141 #define	SPEED232_SEIKO_TIMESYS_TDC_300	B2400   /* UART speed (2400 baud) */
142 #define	SPEED232_TELEPHONE		B2400   /* UART speed (4800 baud) */
143 #define	REFID   	"JJY"		/* reference ID */
144 #define	DESCRIPTION	"JJY Receiver"
145 #define	PRECISION	(-3)		/* precision assumed (about 100 ms) */
146 
147 /*
148  * JJY unit control structure
149  */
150 
151 struct jjyRawDataBreak {
152 	const char *	pString ;
153 	int 		iLength ;
154 } ;
155 
156 #define	MAX_TIMESTAMP	6
157 #define	MAX_RAWBUF   	100
158 #define	MAX_LOOPBACK	5
159 
160 struct jjyunit {
161 /* Set up by the function "jjy_start_xxxxxxxx" */
162 	char	unittype ;	    /* UNITTYPE_XXXXXXXXXX */
163 	short   operationmode ;	    /* Echo Keisokuki LT-2000 */
164 	int 	linespeed ;         /* SPEED232_XXXXXXXXXX */
165 	short	linediscipline ;    /* LDISC_CLK or LDISC_RAW */
166 /* Receiving data */
167 	char	bInitError ;        /* Set by jjy_start if any error during initialization */
168 	short	iProcessState ;     /* JJY_PROCESS_STATE_XXXXXX */
169 	char	bReceiveFlag ;      /* Set and reset by jjy_receive */
170 	char	bLineError ;	    /* Reset by jjy_poll / Set by jjy_receive_xxxxxxxx*/
171 	short	iCommandSeq ;       /* 0:Idle  Non-Zero:Issued */
172 	short	iReceiveSeq ;
173 	int 	iLineCount ;
174 	int 	year, month, day, hour, minute, second, msecond ;
175 	int 	leapsecond ;
176 	int 	iTimestampCount ;   /* TS-JJY01, TS-GPS01, Telephone-JJY */
177 	int 	iTimestamp [ MAX_TIMESTAMP ] ;  /* Serial second ( 0 - 86399 ) */
178 /* LDISC_RAW only */
179 	char	sRawBuf [ MAX_RAWBUF ] ;
180 	int 	iRawBufLen ;
181 	struct	jjyRawDataBreak *pRawBreak ;
182 	char	bWaitBreakString ;
183 	char	sLineBuf [ MAX_RAWBUF ] ;
184 	int 	iLineBufLen ;
185 	char	sTextBuf [ MAX_RAWBUF ] ;
186 	int 	iTextBufLen ;
187 	char	bSkipCntrlCharOnly ;
188 /* Telephone JJY auto measurement of the loopback delay */
189 	char	bLoopbackMode ;
190 	short	iLoopbackCount ;
191 	struct	timeval sendTime[MAX_LOOPBACK], delayTime[MAX_LOOPBACK] ;
192 	char	bLoopbackTimeout[MAX_LOOPBACK] ;
193 	short	iLoopbackValidCount ;
194 /* Telephone JJY timer */
195 	short	iTeljjySilentTimer ;
196 	short	iTeljjyStateTimer ;
197 /* Telephone JJY control finite state machine */
198 	short	iClockState ;
199 	short	iClockEvent ;
200 	short	iClockCommandSeq ;
201 /* Modem timer */
202 	short	iModemSilentCount ;
203 	short	iModemSilentTimer ;
204 	short	iModemStateTimer ;
205 /* Modem control finite state machine */
206 	short	iModemState ;
207 	short	iModemEvent ;
208 	short	iModemCommandSeq ;
209 };
210 
211 #define	UNITTYPE_TRISTATE_JJY01		1
212 #define	UNITTYPE_CDEX_JST2000		2
213 #define	UNITTYPE_ECHOKEISOKUKI_LT2000  	3
214 #define	UNITTYPE_CITIZENTIC_JJY200  	4
215 #define	UNITTYPE_TRISTATE_GPSCLOCK01	5
216 #define	UNITTYPE_SEIKO_TIMESYS_TDC_300	6
217 #define	UNITTYPE_TELEPHONE		100
218 
219 #define	JJY_PROCESS_STATE_IDLE   	0
220 #define	JJY_PROCESS_STATE_POLL   	1
221 #define	JJY_PROCESS_STATE_RECEIVE	2
222 #define	JJY_PROCESS_STATE_DONE   	3
223 #define	JJY_PROCESS_STATE_ERROR  	4
224 
225 /**********************************************************************/
226 
227 /*
228  *  Function calling structure
229  *
230  *  jjy_start
231  *   |--  jjy_start_tristate_jjy01
232  *   |--  jjy_start_cdex_jst2000
233  *   |--  jjy_start_echokeisokuki_lt2000
234  *   |--  jjy_start_citizentic_jjy200
235  *   |--  jjy_start_tristate_gpsclock01
236  *   |--  jjy_start_seiko_tsys_tdc_300
237  *   |--  jjy_start_telephone
238  *
239  *  jjy_shutdown
240  *
241  *  jjy_poll
242  *   |--  jjy_poll_tristate_jjy01
243  *   |--  jjy_poll_cdex_jst2000
244  *   |--  jjy_poll_echokeisokuki_lt2000
245  *   |--  jjy_poll_citizentic_jjy200
246  *   |--  jjy_poll_tristate_gpsclock01
247  *   |--  jjy_poll_seiko_tsys_tdc_300
248  *   |--  jjy_poll_telephone
249  *         |--  teljjy_control
250  *               |--  teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
251  *                     |--  modem_connect
252  *                           |--  modem_control
253  *                                 |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
254  *
255  *  jjy_receive
256  *   |
257  *   |--  jjy_receive_tristate_jjy01
258  *   |     |--  jjy_synctime
259  *   |--  jjy_receive_cdex_jst2000
260  *   |     |--  jjy_synctime
261  *   |--  jjy_receive_echokeisokuki_lt2000
262  *   |     |--  jjy_synctime
263  *   |--  jjy_receive_citizentic_jjy200
264  *   |     |--  jjy_synctime
265  *   |--  jjy_receive_tristate_gpsclock01
266  *   |     |--  jjy_synctime
267  *   |--  jjy_receive_seiko_tsys_tdc_300
268  *   |     |--  jjy_synctime
269  *   |--  jjy_receive_telephone
270  *         |--  modem_receive
271  *         |     |--  modem_control
272  *         |           |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
273  *         |--  teljjy_control
274  *               |--  teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
275  *                     |--  jjy_synctime
276  *                     |--  modem_disconnect
277  *                           |--  modem_control
278  *                                 |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
279  *
280  *  jjy_timer
281  *   |--  jjy_timer_telephone
282  *         |--  modem_timer
283  *         |     |--  modem_control
284  *         |           |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
285  *         |--  teljjy_control
286  *               |--  teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
287  *                     |--  modem_disconnect
288  *                           |--  modem_control
289  *                                 |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
290  *
291  * Function prototypes
292  */
293 
294 static	int 	jjy_start			(int, struct peer *);
295 static	int 	jjy_start_tristate_jjy01	(int, struct peer *, struct jjyunit *);
296 static	int 	jjy_start_cdex_jst2000		(int, struct peer *, struct jjyunit *);
297 static	int 	jjy_start_echokeisokuki_lt2000	(int, struct peer *, struct jjyunit *);
298 static	int 	jjy_start_citizentic_jjy200	(int, struct peer *, struct jjyunit *);
299 static	int 	jjy_start_tristate_gpsclock01	(int, struct peer *, struct jjyunit *);
300 static	int 	jjy_start_seiko_tsys_tdc_300	(int, struct peer *, struct jjyunit *);
301 static	int 	jjy_start_telephone		(int, struct peer *, struct jjyunit *);
302 
303 static	void	jjy_shutdown			(int, struct peer *);
304 
305 static	void	jjy_poll		    	(int, struct peer *);
306 static	void	jjy_poll_tristate_jjy01	    	(int, struct peer *);
307 static	void	jjy_poll_cdex_jst2000	    	(int, struct peer *);
308 static	void	jjy_poll_echokeisokuki_lt2000	(int, struct peer *);
309 static	void	jjy_poll_citizentic_jjy200	(int, struct peer *);
310 static	void	jjy_poll_tristate_gpsclock01	(int, struct peer *);
311 static	void	jjy_poll_seiko_tsys_tdc_300	(int, struct peer *);
312 static	void	jjy_poll_telephone		(int, struct peer *);
313 
314 static	void	jjy_receive			(struct recvbuf *);
315 static	int 	jjy_receive_tristate_jjy01	(struct recvbuf *);
316 static	int 	jjy_receive_cdex_jst2000	(struct recvbuf *);
317 static	int 	jjy_receive_echokeisokuki_lt2000 (struct recvbuf *);
318 static  int 	jjy_receive_citizentic_jjy200	(struct recvbuf *);
319 static	int 	jjy_receive_tristate_gpsclock01	(struct recvbuf *);
320 static	int 	jjy_receive_seiko_tsys_tdc_300	(struct recvbuf *);
321 static	int 	jjy_receive_telephone		(struct recvbuf *);
322 
323 static	void	jjy_timer			(int, struct peer *);
324 static	void	jjy_timer_telephone		(int, struct peer *);
325 
326 static	void	jjy_synctime			( struct peer *, struct refclockproc *, struct jjyunit * ) ;
327 static	void	jjy_write_clockstats		( struct peer *, int, const char* ) ;
328 
329 static	int 	getRawDataBreakPosition		( struct jjyunit *, int ) ;
330 
331 static	short	getModemState			( struct jjyunit * ) ;
332 static	int 	isModemStateConnect		( short ) ;
333 static	int 	isModemStateDisconnect		( short ) ;
334 static	int 	isModemStateTimerOn		( struct jjyunit * ) ;
335 static	void	modem_connect			( int, struct peer * ) ;
336 static	void	modem_disconnect		( int, struct peer * ) ;
337 static	int 	modem_receive			( struct recvbuf * ) ;
338 static	void	modem_timer			( int, struct peer * );
339 
340 static	void	printableString ( char*, int, const char*, int ) ;
341 
342 /*
343  * Transfer vector
344  */
345 struct	refclock refclock_jjy = {
346 	jjy_start,	/* start up driver */
347 	jjy_shutdown,	/* shutdown driver */
348 	jjy_poll,	/* transmit poll message */
349 	noentry,	/* not used */
350 	noentry,	/* not used */
351 	noentry,	/* not used */
352 	jjy_timer	/* 1 second interval timer */
353 };
354 
355 /*
356  * Start up driver return code
357  */
358 #define	RC_START_SUCCESS	1
359 #define	RC_START_ERROR		0
360 
361 /*
362  * Local constants definition
363  */
364 
365 #define	MAX_LOGTEXT	100
366 
367 #ifndef	TRUE
368 #define	TRUE	(0==0)
369 #endif
370 #ifndef	FALSE
371 #define	FALSE	(!TRUE)
372 #endif
373 
374 /* Local constants definition for the return code of the jjy_receive_xxxxxxxx */
375 
376 #define	JJY_RECEIVE_DONE	0
377 #define	JJY_RECEIVE_SKIP	1
378 #define	JJY_RECEIVE_UNPROCESS	2
379 #define	JJY_RECEIVE_WAIT	3
380 #define	JJY_RECEIVE_ERROR	4
381 
382 /* Local constants definition for the 2nd parameter of the jjy_write_clockstats */
383 
384 #define	JJY_CLOCKSTATS_MARK_NONE	0
385 #define	JJY_CLOCKSTATS_MARK_JJY 	1
386 #define	JJY_CLOCKSTATS_MARK_SEND	2
387 #define	JJY_CLOCKSTATS_MARK_RECEIVE	3
388 #define	JJY_CLOCKSTATS_MARK_INFORMATION	4
389 #define	JJY_CLOCKSTATS_MARK_ATTENTION	5
390 #define	JJY_CLOCKSTATS_MARK_WARNING	6
391 #define	JJY_CLOCKSTATS_MARK_ERROR	7
392 
393 /* Local constants definition for the clockstats messages */
394 
395 #define	JJY_CLOCKSTATS_MESSAGE_ECHOBACK         	"* Echoback"
396 #define	JJY_CLOCKSTATS_MESSAGE_IGNORE_REPLY     	"* Ignore replay : [%s]"
397 #define	JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2  	"* Over midnight : timestamp=%d, %d"
398 #define	JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_3  	"* Over midnight : timestamp=%d, %d, %d"
399 #define	JJY_CLOCKSTATS_MESSAGE_TIMESTAMP_UNSURE 	"* Unsure timestamp : %s"
400 #define	JJY_CLOCKSTATS_MESSAGE_LOOPBACK_DELAY   	"* Loopback delay : %d.%03d mSec."
401 #define	JJY_CLOCKSTATS_MESSAGE_DELAY_ADJUST     	"* Delay adjustment : %d mSec. ( valid=%hd/%d )"
402 #define	JJY_CLOCKSTATS_MESSAGE_DELAY_UNADJUST   	"* Delay adjustment : None ( valid=%hd/%d )"
403 
404 #define	JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY     	"# Unexpected reply : [%s]"
405 #define	JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH     	"# Invalid length : length=%d"
406 #define	JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY     	"# Too many reply : count=%d"
407 #define	JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY      	"# Invalid reply : [%s]"
408 #define	JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2       	"# Slow reply : timestamp=%d, %d"
409 #define	JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_3       	"# Slow reply : timestamp=%d, %d, %d"
410 #define	JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE	"# Invalid date : rc=%d year=%d month=%d day=%d"
411 #define	JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME	"# Invalid time : rc=%d hour=%d minute=%d second=%d"
412 #define	JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME	"# Invalid time : rc=%d year=%d month=%d day=%d hour=%d minute=%d second=%d"
413 #define	JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_LEAP	"# Invalid leap : leapsecond=[%s]"
414 #define	JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_STATUS	"# Invalid status : status=[%s]"
415 
416 /* Debug print macro */
417 
418 #ifdef	DEBUG
419 #define	DEBUG_PRINTF_JJY_RECEIVE(sFunc,iLen)	{ if ( debug ) { printf ( "refclock_jjy.c : %s : iProcessState=%d bLineError=%d iCommandSeq=%d iLineCount=%d iTimestampCount=%d iLen=%d\n", sFunc, up->iProcessState, up->bLineError, up->iCommandSeq, up->iLineCount, up->iTimestampCount, iLen ) ; } }
420 #else
421 #define	DEBUG_PRINTF_JJY_RECEIVE(sFunc,iLen)
422 #endif
423 
424 /**************************************************************************************************/
425 /*  jjy_start - open the devices and initialize data for processing                               */
426 /**************************************************************************************************/
427 static int
428 jjy_start ( int unit, struct peer *peer )
429 {
430 
431 	struct	refclockproc *pp ;
432 	struct	jjyunit      *up ;
433 	int 	rc ;
434 	int 	fd ;
435 	char	sDeviceName [ sizeof(DEVICE) + 10 ], sLog [ 60 ] ;
436 
437 #ifdef DEBUG
438 	if ( debug ) {
439 		printf( "refclock_jjy.c : jjy_start : %s  mode=%d  dev=%s  unit=%d\n",
440 			 ntoa(&peer->srcadr), peer->ttl, DEVICE, unit ) ;
441 	}
442 #endif
443 
444 	/* Allocate memory for the unit structure */
445 	up = emalloc( sizeof(*up) ) ;
446 	if ( up == NULL ) {
447 		msyslog ( LOG_ERR, "refclock_jjy.c : jjy_start : emalloc" ) ;
448 		return RC_START_ERROR ;
449 	}
450 	memset ( up, 0, sizeof(*up) ) ;
451 
452 	up->bInitError = FALSE ;
453 	up->iProcessState = JJY_PROCESS_STATE_IDLE ;
454 	up->bReceiveFlag = FALSE ;
455 	up->iCommandSeq = 0 ;
456 	up->iLineCount = 0 ;
457 	up->iTimestampCount = 0 ;
458 	up->bWaitBreakString = FALSE ;
459 	up->iRawBufLen = up->iLineBufLen = up->iTextBufLen = 0 ;
460 	up->bSkipCntrlCharOnly = TRUE ;
461 
462 	/* Set up the device name */
463 	snprintf( sDeviceName, sizeof(sDeviceName), DEVICE, unit ) ;
464 
465 	snprintf( sLog, sizeof(sLog), "mode=%d dev=%s", peer->ttl, sDeviceName ) ;
466 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
467 
468 	/*
469 	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
470 	 */
471 	switch ( peer->ttl ) {
472 	case 0 :
473 	case 1 :
474 		rc = jjy_start_tristate_jjy01 ( unit, peer, up ) ;
475 		break ;
476 	case 2 :
477 		rc = jjy_start_cdex_jst2000 ( unit, peer, up ) ;
478 		break ;
479 	case 3 :
480 		rc = jjy_start_echokeisokuki_lt2000 ( unit, peer, up ) ;
481 		break ;
482 	case 4 :
483 		rc = jjy_start_citizentic_jjy200 ( unit, peer, up ) ;
484 		break ;
485 	case 5 :
486 		rc = jjy_start_tristate_gpsclock01 ( unit, peer, up ) ;
487 		break ;
488 	case 6 :
489 		rc = jjy_start_seiko_tsys_tdc_300 ( unit, peer, up ) ;
490 		break ;
491 	case 100 :
492 		rc = jjy_start_telephone ( unit, peer, up ) ;
493 		break ;
494 	default :
495 		if ( 101 <= peer->ttl && peer->ttl <= 180 ) {
496 			rc = jjy_start_telephone ( unit, peer, up ) ;
497 		} else {
498 			msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
499 				  ntoa(&peer->srcadr), peer->ttl ) ;
500 			free ( (void*) up ) ;
501 		return RC_START_ERROR ;
502 		}
503 	}
504 
505 	if ( rc != 0 ) {
506 		msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Initialize error",
507 			  ntoa(&peer->srcadr), peer->ttl ) ;
508 		free ( (void*) up ) ;
509 		return RC_START_ERROR ;
510 	}
511 
512 	/* Open the device */
513 	fd = refclock_open ( sDeviceName, up->linespeed, up->linediscipline ) ;
514 	if ( fd <= 0 ) {
515 		free ( (void*) up ) ;
516 		return RC_START_ERROR ;
517 	}
518 
519 	/*
520 	 * Initialize variables
521 	 */
522 	pp = peer->procptr ;
523 
524 	pp->clockdesc	= DESCRIPTION ;
525 	pp->unitptr       = up ;
526 	pp->io.clock_recv = jjy_receive ;
527 	pp->io.srcclock   = peer ;
528 	pp->io.datalen	  = 0 ;
529 	pp->io.fd	  = fd ;
530 	if ( ! io_addclock(&pp->io) ) {
531 		close ( fd ) ;
532 		pp->io.fd = -1 ;
533 		free ( up ) ;
534 		pp->unitptr = NULL ;
535 		return RC_START_ERROR ;
536 	}
537 	memcpy( (char*)&pp->refid, REFID, strlen(REFID) ) ;
538 
539 	peer->precision = PRECISION ;
540 
541 	snprintf( sLog, sizeof(sLog), "minpoll=%d maxpoll=%d", peer->minpoll, peer->maxpoll ) ;
542 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
543 
544 	return RC_START_SUCCESS ;
545 
546 }
547 
548 /**************************************************************************************************/
549 /*  jjy_shutdown - shutdown the clock                                                             */
550 /**************************************************************************************************/
551 static void
552 jjy_shutdown ( int unit, struct peer *peer )
553 {
554 
555 	struct jjyunit	    *up;
556 	struct refclockproc *pp;
557 
558 	char	sLog [ 60 ] ;
559 
560 	pp = peer->procptr ;
561 	up = pp->unitptr ;
562 	if ( -1 != pp->io.fd ) {
563 		io_closeclock ( &pp->io ) ;
564 	}
565 	if ( NULL != up ) {
566 		free ( up ) ;
567 	}
568 
569 	snprintf( sLog, sizeof(sLog), "JJY stopped. unit=%d mode=%d", unit, peer->ttl ) ;
570 	record_clock_stats( &peer->srcadr, sLog ) ;
571 
572 }
573 
574 /**************************************************************************************************/
575 /*  jjy_receive - receive data from the serial interface                                          */
576 /**************************************************************************************************/
577 static void
578 jjy_receive ( struct recvbuf *rbufp )
579 {
580 #ifdef DEBUG
581 	static const char *sFunctionName = "jjy_receive" ;
582 #endif
583 
584 	struct jjyunit	    *up ;
585 	struct refclockproc *pp ;
586 	struct peer	    *peer;
587 
588 	l_fp	tRecvTimestamp;		/* arrival timestamp */
589 	int 	rc ;
590 	char	*pBuf, sLogText [ MAX_LOGTEXT ] ;
591 	int 	iLen, iCopyLen ;
592 	int 	i, j, iReadRawBuf, iBreakPosition ;
593 
594 	/*
595 	 * Initialize pointers and read the timecode and timestamp
596 	 */
597 	peer = rbufp->recv_peer ;
598 	pp = peer->procptr ;
599 	up = pp->unitptr ;
600 
601 	/*
602 	 * Get next input line
603 	 */
604 	if ( up->linediscipline == LDISC_RAW ) {
605 
606 		pp->lencode  = refclock_gtraw ( rbufp, pp->a_lastcode, BMAX-1, &tRecvTimestamp ) ;
607 		/* 3rd argument can be BMAX, but the coverity scan tool claim "Memory - corruptions  (OVERRUN)" */
608 		/* "a_lastcode" is defined as "char a_lastcode[BMAX]" in the ntp_refclock.h */
609 		/* To avoid its claim, pass the value BMAX-1. */
610 
611 		/*
612 		 * Append received charaters to temporary buffer
613 		 */
614 		for ( i = 0 ;
615 		      i < pp->lencode && up->iRawBufLen < MAX_RAWBUF - 2 ;
616 		      i ++ , up->iRawBufLen ++ ) {
617 			up->sRawBuf[up->iRawBufLen] = pp->a_lastcode[i] ;
618 		}
619 		up->sRawBuf[up->iRawBufLen] = 0 ;
620 
621 
622 	} else {
623 
624 		pp->lencode  = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
625 
626 	}
627 #ifdef DEBUG
628 	printf( "\nrefclock_jjy.c : %s : Len=%d  ", sFunctionName, pp->lencode ) ;
629 	for ( i = 0 ; i < pp->lencode ; i ++ ) {
630 		if ( iscntrl( (u_char)(pp->a_lastcode[i] & 0x7F) ) ) {
631 			printf( "<x%02X>", pp->a_lastcode[i] & 0xFF ) ;
632 		} else {
633 			printf( "%c", pp->a_lastcode[i] ) ;
634 		}
635 	}
636 	printf( "\n" ) ;
637 #endif
638 
639 	/*
640 	 * The reply with <CR><LF> gives a blank line
641 	 */
642 
643 	if ( pp->lencode == 0 ) return ;
644 
645 	/*
646 	 * Receiving data is not expected
647 	 */
648 
649 	if ( up->iProcessState == JJY_PROCESS_STATE_IDLE
650 	  || up->iProcessState == JJY_PROCESS_STATE_DONE
651 	  || up->iProcessState == JJY_PROCESS_STATE_ERROR ) {
652 		/* Discard received data */
653 		up->iRawBufLen = 0 ;
654 #ifdef DEBUG
655 		if ( debug ) {
656 			printf( "refclock_jjy.c : %s : Discard received data\n", sFunctionName ) ;
657 		}
658 #endif
659 		return ;
660 	}
661 
662 	/*
663 	 * We get down to business
664 	 */
665 
666 	pp->lastrec = tRecvTimestamp ;
667 
668 	up->iLineCount ++ ;
669 
670 	up->iProcessState = JJY_PROCESS_STATE_RECEIVE ;
671 	up->bReceiveFlag = TRUE ;
672 
673 	iReadRawBuf = 0 ;
674 	iBreakPosition = up->iRawBufLen - 1 ;
675 	for ( ; up->iProcessState == JJY_PROCESS_STATE_RECEIVE ; ) {
676 
677 		if ( up->linediscipline == LDISC_RAW ) {
678 
679 			if ( up->bWaitBreakString ) {
680 				iBreakPosition = getRawDataBreakPosition( up, iReadRawBuf ) ;
681 				if ( iBreakPosition == -1 ) {
682 					/* Break string have not come yet */
683 					if ( up->iRawBufLen < MAX_RAWBUF - 2
684 					  || iReadRawBuf > 0 ) {
685 						/* Temporary buffer is not full */
686 						break ;
687 					} else {
688 						/* Temporary buffer is full */
689 						iBreakPosition = up->iRawBufLen - 1 ;
690 					}
691 				}
692 			} else {
693 				iBreakPosition = up->iRawBufLen - 1 ;
694 			}
695 
696 			/* Copy charaters from temporary buffer to process buffer */
697 			up->iLineBufLen = up->iTextBufLen = 0 ;
698 			for ( i = iReadRawBuf ; i <= iBreakPosition ; i ++ ) {
699 
700 				/* Copy all characters */
701 				up->sLineBuf[up->iLineBufLen] = up->sRawBuf[i] ;
702 				up->iLineBufLen ++ ;
703 
704 				/* Copy printable characters */
705 				if ( ! iscntrl( (u_char)up->sRawBuf[i] ) ) {
706 					up->sTextBuf[up->iTextBufLen] = up->sRawBuf[i] ;
707 					up->iTextBufLen ++ ;
708 				}
709 
710 			}
711 			up->sLineBuf[up->iLineBufLen] = 0 ;
712 			up->sTextBuf[up->iTextBufLen] = 0 ;
713 #ifdef DEBUG
714 			printf( "refclock_jjy.c : %s : up->iLineBufLen=%d up->iTextBufLen=%d\n",
715 				 sFunctionName, up->iLineBufLen, up->iTextBufLen ) ;
716 #endif
717 
718 			if ( up->bSkipCntrlCharOnly && up->iTextBufLen == 0 ) {
719 #ifdef DEBUG
720 				printf( "refclock_jjy.c : %s : Skip cntrl char only : up->iRawBufLen=%d iReadRawBuf=%d iBreakPosition=%d\n",
721 					 sFunctionName, up->iRawBufLen, iReadRawBuf, iBreakPosition ) ;
722 #endif
723 				if ( iBreakPosition + 1 < up->iRawBufLen ) {
724 					iReadRawBuf = iBreakPosition + 1 ;
725 					continue ;
726 				} else {
727 					break ;
728 				}
729 
730 			}
731 
732 		}
733 
734 		if ( up->linediscipline == LDISC_RAW ) {
735 			pBuf = up->sLineBuf ;
736 			iLen = up->iLineBufLen ;
737 		} else {
738 			pBuf = pp->a_lastcode ;
739 			iLen = pp->lencode ;
740 		}
741 
742 		iCopyLen = ( iLen <= sizeof(sLogText)-1 ? iLen : sizeof(sLogText)-1 ) ;
743 		strncpy( sLogText, pBuf, iCopyLen ) ;
744 		sLogText[iCopyLen] = 0 ;
745 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_RECEIVE, sLogText ) ;
746 
747 		switch ( up->unittype ) {
748 
749 		case UNITTYPE_TRISTATE_JJY01 :
750 			rc = jjy_receive_tristate_jjy01  ( rbufp ) ;
751 			break ;
752 
753 		case UNITTYPE_CDEX_JST2000 :
754 			rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
755 			break ;
756 
757 		case UNITTYPE_ECHOKEISOKUKI_LT2000 :
758 			rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
759 			break ;
760 
761 		case UNITTYPE_CITIZENTIC_JJY200 :
762 			rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
763 			break ;
764 
765 		case UNITTYPE_TRISTATE_GPSCLOCK01 :
766 			rc = jjy_receive_tristate_gpsclock01 ( rbufp ) ;
767 			break ;
768 
769 		case UNITTYPE_SEIKO_TIMESYS_TDC_300 :
770 			rc = jjy_receive_seiko_tsys_tdc_300 ( rbufp ) ;
771 			break ;
772 
773 		case UNITTYPE_TELEPHONE :
774 			rc = jjy_receive_telephone ( rbufp ) ;
775 			break ;
776 
777 		default :
778 			rc = JJY_RECEIVE_ERROR ;
779 			break ;
780 
781 		}
782 
783 		switch ( rc ) {
784 		case JJY_RECEIVE_DONE :
785 		case JJY_RECEIVE_SKIP :
786 			up->iProcessState = JJY_PROCESS_STATE_DONE ;
787 			break ;
788 		case JJY_RECEIVE_ERROR :
789 			up->iProcessState = JJY_PROCESS_STATE_ERROR ;
790 			break ;
791 		default :
792 			break ;
793 		}
794 
795 		if ( up->linediscipline == LDISC_RAW ) {
796 			if ( rc == JJY_RECEIVE_UNPROCESS ) {
797 				break ;
798 			}
799 			iReadRawBuf = iBreakPosition + 1 ;
800 			if ( iReadRawBuf >= up->iRawBufLen ) {
801 				/* Processed all received data */
802 				break ;
803 			}
804 		}
805 
806 		if ( up->linediscipline == LDISC_CLK ) {
807 			break ;
808 		}
809 
810 	}
811 
812 	if ( up->linediscipline == LDISC_RAW && iReadRawBuf > 0 ) {
813 		for ( i = 0, j = iReadRawBuf ; j < up->iRawBufLen ; i ++, j++ ) {
814 			up->sRawBuf[i] = up->sRawBuf[j] ;
815 		}
816 		up->iRawBufLen -= iReadRawBuf ;
817 		if ( up->iRawBufLen < 0 ) {
818 			up->iRawBufLen = 0 ;
819 		}
820 	}
821 
822 	up->bReceiveFlag = FALSE ;
823 
824 }
825 
826 /**************************************************************************************************/
827 
828 static int
829 getRawDataBreakPosition ( struct jjyunit *up, int iStart )
830 {
831 
832 	int 	i, j ;
833 
834 	if ( iStart >= up->iRawBufLen ) {
835 #ifdef DEBUG
836 		printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=-1\n", iStart ) ;
837 #endif
838 		return -1 ;
839 	}
840 
841 	for ( i = iStart ; i < up->iRawBufLen ; i ++ ) {
842 
843 		for ( j = 0 ; up->pRawBreak[j].pString != NULL ; j ++ ) {
844 
845 			if ( i + up->pRawBreak[j].iLength <= up->iRawBufLen ) {
846 
847 				if ( strncmp( up->sRawBuf + i,
848 					up->pRawBreak[j].pString,
849 					up->pRawBreak[j].iLength ) == 0 ) {
850 
851 #ifdef DEBUG
852 					printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=%d\n",
853 						iStart, i + up->pRawBreak[j].iLength - 1 ) ;
854 #endif
855 					return i + up->pRawBreak[j].iLength - 1 ;
856 
857 				}
858 			}
859 		}
860 	}
861 
862 #ifdef DEBUG
863 	printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=-1\n", iStart ) ;
864 #endif
865 	return -1 ;
866 
867 }
868 
869 /**************************************************************************************************/
870 /*  jjy_poll - called by the transmit procedure                                                   */
871 /**************************************************************************************************/
872 static void
873 jjy_poll ( int unit, struct peer *peer )
874 {
875 
876 	char	sLog [ 40 ], sReach [ 9 ] ;
877 
878 	struct jjyunit      *up;
879 	struct refclockproc *pp;
880 
881 	pp = peer->procptr;
882 	up = pp->unitptr ;
883 
884 	if ( up->bInitError ) {
885 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, "Ignore polling because of error during initializing" ) ;
886 		return ;
887 	}
888 
889 	if ( pp->polls > 0  &&  up->iLineCount == 0 ) {
890 		/*
891 		 * No reply for last command
892 		 */
893 		refclock_report ( peer, CEVNT_TIMEOUT ) ;
894 	}
895 
896 	pp->polls ++ ;
897 
898 	sReach[0] = peer->reach & 0x80 ? '1' : '0' ;
899 	sReach[1] = peer->reach & 0x40 ? '1' : '0' ;
900 	sReach[2] = peer->reach & 0x20 ? '1' : '0' ;
901 	sReach[3] = peer->reach & 0x10 ? '1' : '0' ;
902 	sReach[4] = peer->reach & 0x08 ? '1' : '0' ;
903 	sReach[5] = peer->reach & 0x04 ? '1' : '0' ;
904 	sReach[6] = peer->reach & 0x02 ? '1' : '0' ;
905 	sReach[7] = 0 ; /* This poll */
906 	sReach[8] = 0 ;
907 
908 	snprintf( sLog, sizeof(sLog), "polls=%ld reach=%s", pp->polls, sReach ) ;
909 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ATTENTION, sLog ) ;
910 
911 	up->iProcessState = JJY_PROCESS_STATE_POLL ;
912 	up->iCommandSeq = 0 ;
913 	up->iReceiveSeq = 0 ;
914 	up->iLineCount = 0 ;
915 	up->bLineError = FALSE ;
916 	up->iRawBufLen = 0 ;
917 
918 	switch ( up->unittype ) {
919 
920 	case UNITTYPE_TRISTATE_JJY01 :
921 		jjy_poll_tristate_jjy01  ( unit, peer ) ;
922 		break ;
923 
924 	case UNITTYPE_CDEX_JST2000 :
925 		jjy_poll_cdex_jst2000 ( unit, peer ) ;
926 		break ;
927 
928 	case UNITTYPE_ECHOKEISOKUKI_LT2000 :
929 		jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
930 		break ;
931 
932 	case UNITTYPE_CITIZENTIC_JJY200 :
933 		jjy_poll_citizentic_jjy200 ( unit, peer ) ;
934 		break ;
935 
936 	case UNITTYPE_TRISTATE_GPSCLOCK01 :
937 		jjy_poll_tristate_gpsclock01 ( unit, peer ) ;
938 		break ;
939 
940 	case UNITTYPE_SEIKO_TIMESYS_TDC_300 :
941 		jjy_poll_seiko_tsys_tdc_300 ( unit, peer ) ;
942 		break ;
943 
944 	case UNITTYPE_TELEPHONE :
945 		jjy_poll_telephone ( unit, peer ) ;
946 		break ;
947 
948 	default :
949 		break ;
950 
951 	}
952 
953 }
954 
955 /**************************************************************************************************/
956 /*  jjy_timer - called at one-second intervals                                                    */
957 /**************************************************************************************************/
958 static void
959 jjy_timer ( int unit, struct peer *peer )
960 {
961 
962 	struct	refclockproc *pp ;
963 	struct	jjyunit      *up ;
964 
965 #ifdef DEBUG
966 	if ( debug ) {
967 		printf ( "refclock_jjy.c : jjy_timer\n" ) ;
968 	}
969 #endif
970 
971 	pp = peer->procptr ;
972 	up = pp->unitptr ;
973 
974 	if ( up->bReceiveFlag ) {
975 #ifdef DEBUG
976 		if ( debug ) {
977 			printf ( "refclock_jjy.c : jjy_timer : up->bReceiveFlag= TRUE : Timer skipped.\n" ) ;
978 		}
979 #endif
980 		return ;
981 	}
982 
983 	switch ( up->unittype ) {
984 
985 	case UNITTYPE_TELEPHONE :
986 		jjy_timer_telephone ( unit, peer ) ;
987 		break ;
988 
989 	default :
990 		break ;
991 
992 	}
993 
994 }
995 
996 /**************************************************************************************************/
997 /*  jjy_synctime                                                                                  */
998 /**************************************************************************************************/
999 static void
1000 jjy_synctime ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
1001 {
1002 
1003 	char	sLog [ 80 ], cStatus ;
1004 	const char	*pStatus ;
1005 
1006 	pp->year   = up->year ;
1007 	pp->day    = ymd2yd( up->year, up->month, up->day ) ;
1008 	pp->hour   = up->hour ;
1009 	pp->minute = up->minute ;
1010 	pp->second = up->second ;
1011 	pp->nsec   = up->msecond * 1000000 ;
1012 
1013 	/*
1014 	 * JST to UTC
1015 	 */
1016 	pp->hour -= 9 ;
1017 	if ( pp->hour < 0 ) {
1018 		pp->hour += 24 ;
1019 		pp->day -- ;
1020 		if ( pp->day < 1 ) {
1021 			pp->year -- ;
1022 			pp->day  = ymd2yd( pp->year, 12, 31 ) ;
1023 		}
1024 	}
1025 
1026 	/*
1027 	 * Process the new sample in the median filter and determine the
1028 	 * timecode timestamp.
1029 	 */
1030 
1031 	if ( ! refclock_process( pp ) ) {
1032 		refclock_report( peer, CEVNT_BADTIME ) ;
1033 		return ;
1034 	}
1035 
1036 	pp->lastref = pp->lastrec ;
1037 
1038 	refclock_receive( peer ) ;
1039 
1040 	/*
1041 	 * Write into the clockstats file
1042 	 */
1043 	snprintf ( sLog, sizeof(sLog),
1044 		   "%04d/%02d/%02d %02d:%02d:%02d.%03d JST   ( %04d/%03d %02d:%02d:%02d.%03d UTC )",
1045 		   up->year, up->month, up->day,
1046 		   up->hour, up->minute, up->second, up->msecond,
1047 		   pp->year, pp->day, pp->hour, pp->minute, pp->second,
1048 		   (int)(pp->nsec/1000000) ) ;
1049 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ATTENTION, sLog ) ;
1050 
1051 	cStatus = ' ' ;
1052 	pStatus = "" ;
1053 
1054 	switch ( peer->status ) {
1055 	case 0 : cStatus = ' ' ; pStatus = "Reject"    ; break ;
1056 	case 1 : cStatus = 'x' ; pStatus = "FalseTick" ; break ;
1057 	case 2 : cStatus = '.' ; pStatus = "Excess"    ; break ;
1058 	case 3 : cStatus = '-' ; pStatus = "Outlier"   ; break ;
1059 	case 4 : cStatus = '+' ; pStatus = "Candidate" ; break ;
1060 	case 5 : cStatus = '#' ; pStatus = "Selected"  ; break ;
1061 	case 6 : cStatus = '*' ; pStatus = "Sys.Peer"  ; break ;
1062 	case 7 : cStatus = 'o' ; pStatus = "PPS.Peer"  ; break ;
1063 	default : break ;
1064 	}
1065 
1066 	snprintf ( sLog, sizeof(sLog),
1067 		   "status %d [%c] %s : offset %3.3f mSec. : jitter %3.3f mSec.",
1068 		    peer->status, cStatus, pStatus, peer->offset * 1000, peer->jitter * 1000 ) ;
1069 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
1070 
1071 }
1072 
1073 /*################################################################################################*/
1074 /*################################################################################################*/
1075 /*##												##*/
1076 /*##    The Tristate Ltd. JJY receiver TS-JJY01, TS-JJY02					##*/
1077 /*##												##*/
1078 /*##    server  127.127.40.X  mode 1								##*/
1079 /*##												##*/
1080 /*################################################################################################*/
1081 /*################################################################################################*/
1082 /*                                                                                                */
1083 /*  Command               Response                                  Remarks                       */
1084 /*  --------------------  ----------------------------------------  ----------------------------  */
1085 /*  dcst<CR><LF>          VALID<CR><LF> or INVALID<CR><LF>                                        */
1086 /*  stus<CR><LF>          ADJUSTED<CR><LF> or UNADJUSTED<CR><LF>                                  */
1087 /*  date<CR><LF>          YYYY/MM/DD XXX<CR><LF>                    XXX is the day of the week    */
1088 /*  time<CR><LF>          HH:MM:SS<CR><LF>                          Not used by this driver       */
1089 /*  stim<CR><LF>          HH:MM:SS<CR><LF>                          Reply at just second          */
1090 /*                                                                                                */
1091 /*################################################################################################*/
1092 
1093 #define	TS_JJY01_COMMAND_NUMBER_DATE	1
1094 #define	TS_JJY01_COMMAND_NUMBER_TIME	2
1095 #define	TS_JJY01_COMMAND_NUMBER_STIM	3
1096 #define	TS_JJY01_COMMAND_NUMBER_STUS	4
1097 #define	TS_JJY01_COMMAND_NUMBER_DCST	5
1098 
1099 #define	TS_JJY01_REPLY_DATE     	"yyyy/mm/dd www"
1100 #define	TS_JJY01_REPLY_STIM     	"hh:mm:ss"
1101 #define	TS_JJY01_REPLY_STUS_ADJUSTED	"adjusted"
1102 #define	TS_JJY01_REPLY_STUS_UNADJUSTED	"unadjusted"
1103 #define	TS_JJY01_REPLY_DCST_VALID	"valid"
1104 #define	TS_JJY01_REPLY_DCST_INVALID	"invalid"
1105 
1106 #define	TS_JJY01_REPLY_LENGTH_DATE           	14	/* Length without <CR><LF> */
1107 #define	TS_JJY01_REPLY_LENGTH_TIME           	8	/* Length without <CR><LF> */
1108 #define	TS_JJY01_REPLY_LENGTH_STIM           	8	/* Length without <CR><LF> */
1109 #define	TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED  	8	/* Length without <CR><LF> */
1110 #define	TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED	10	/* Length without <CR><LF> */
1111 #define	TS_JJY01_REPLY_LENGTH_DCST_VALID     	5	/* Length without <CR><LF> */
1112 #define	TS_JJY01_REPLY_LENGTH_DCST_INVALID   	7	/* Length without <CR><LF> */
1113 
1114 static  struct
1115 {
1116 	const char	commandNumber ;
1117 	const char	*command ;
1118 	int	commandLength ;
1119 	int	iExpectedReplyLength [ 2 ] ;
1120 } tristate_jjy01_command_sequence[] =
1121 {
1122 	{ 0, NULL, 0, { 0, 0 } }, /* Idle */
1123 	{ TS_JJY01_COMMAND_NUMBER_DCST, "dcst\r\n", 6, { TS_JJY01_REPLY_LENGTH_DCST_VALID   , TS_JJY01_REPLY_LENGTH_DCST_INVALID } },
1124 	{ TS_JJY01_COMMAND_NUMBER_STUS, "stus\r\n", 6, { TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED, TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED } },
1125 	{ TS_JJY01_COMMAND_NUMBER_TIME, "time\r\n", 6, { TS_JJY01_REPLY_LENGTH_TIME         , TS_JJY01_REPLY_LENGTH_TIME } },
1126 	{ TS_JJY01_COMMAND_NUMBER_DATE, "date\r\n", 6, { TS_JJY01_REPLY_LENGTH_DATE         , TS_JJY01_REPLY_LENGTH_DATE } },
1127 	{ TS_JJY01_COMMAND_NUMBER_STIM, "stim\r\n", 6, { TS_JJY01_REPLY_LENGTH_STIM         , TS_JJY01_REPLY_LENGTH_STIM } },
1128 	/* End of command */
1129 	{ 0, NULL, 0, { 0, 0 } }
1130 } ;
1131 
1132 /**************************************************************************************************/
1133 
1134 static int
1135 jjy_start_tristate_jjy01 ( int unit, struct peer *peer, struct jjyunit *up )
1136 {
1137 
1138 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Tristate Ltd. TS-JJY01, TS-JJY02" ) ;
1139 
1140 	up->unittype  = UNITTYPE_TRISTATE_JJY01 ;
1141 	up->linespeed = SPEED232_TRISTATE_JJY01 ;
1142 	up->linediscipline = LDISC_CLK ;
1143 
1144 	return 0 ;
1145 
1146 }
1147 
1148 /**************************************************************************************************/
1149 
1150 static int
1151 jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
1152 {
1153 	struct jjyunit	    *up ;
1154 	struct refclockproc *pp ;
1155 	struct peer	    *peer;
1156 
1157 	char *		pBuf ;
1158 	char		sLog [ 100 ] ;
1159 	int 		iLen ;
1160 	int 		rc ;
1161 
1162 	const char *	pCmd ;
1163 	int 		iCmdLen ;
1164 
1165 	/* Initialize pointers  */
1166 
1167 	peer = rbufp->recv_peer ;
1168 	pp = peer->procptr ;
1169 	up = pp->unitptr ;
1170 
1171 	if ( up->linediscipline == LDISC_RAW ) {
1172 		pBuf = up->sTextBuf ;
1173 		iLen = up->iTextBufLen ;
1174 	} else {
1175 		pBuf = pp->a_lastcode ;
1176 		iLen = pp->lencode ;
1177 	}
1178 
1179 	DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_tristate_jjy01", iLen ) ;
1180 
1181 	/* Check expected reply */
1182 
1183 	if ( tristate_jjy01_command_sequence[up->iCommandSeq].command == NULL ) {
1184 		/* Command sequence has not been started, or has been completed */
1185 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
1186 			  pBuf ) ;
1187 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1188 		up->bLineError = TRUE ;
1189 		return JJY_RECEIVE_ERROR ;
1190 	}
1191 
1192 	/* Check reply length */
1193 
1194 	if ( iLen != tristate_jjy01_command_sequence[up->iCommandSeq].iExpectedReplyLength[0]
1195 	  && iLen != tristate_jjy01_command_sequence[up->iCommandSeq].iExpectedReplyLength[1] ) {
1196 		/* Unexpected reply length */
1197 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
1198 			  iLen ) ;
1199 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1200 		up->bLineError = TRUE ;
1201 		return JJY_RECEIVE_ERROR ;
1202 	}
1203 
1204 	/* Parse reply */
1205 
1206 	switch ( tristate_jjy01_command_sequence[up->iCommandSeq].commandNumber ) {
1207 
1208 	case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */
1209 
1210 		rc = sscanf ( pBuf, "%4d/%2d/%2d",
1211 			      &up->year, &up->month, &up->day ) ;
1212 
1213 		if ( rc != 3 || up->year < 2000 || 2099 <= up->year
1214 		  || up->month < 1 || 12 < up->month
1215 		  || up->day < 1 || 31 < up->day ) {
1216 			/* Invalid date */
1217 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE,
1218 				  rc, up->year, up->month, up->day ) ;
1219 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1220 			up->bLineError = TRUE ;
1221 			return JJY_RECEIVE_ERROR ;
1222 		}
1223 
1224 		break ;
1225 
1226 	case TS_JJY01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
1227 	case TS_JJY01_COMMAND_NUMBER_STIM : /* HH:MM:SS */
1228 
1229 		if ( up->iTimestampCount >= 2 ) {
1230 			/* Too many time reply */
1231 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY,
1232 				  up->iTimestampCount ) ;
1233 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1234 			up->bLineError = TRUE ;
1235 			return JJY_RECEIVE_ERROR ;
1236 		}
1237 
1238 		rc = sscanf ( pBuf, "%2d:%2d:%2d",
1239 			      &up->hour, &up->minute, &up->second ) ;
1240 
1241 		if ( rc != 3 || up->hour > 23 || up->minute > 59 ||
1242 		     up->second > 60 ) {
1243 			/* Invalid time */
1244 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
1245 				  rc, up->hour, up->minute, up->second ) ;
1246 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1247 			up->bLineError = TRUE ;
1248 			return JJY_RECEIVE_ERROR ;
1249 		}
1250 
1251 		up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ;
1252 
1253 		up->iTimestampCount++ ;
1254 
1255 		up->msecond = 0 ;
1256 
1257 		break ;
1258 
1259 	case TS_JJY01_COMMAND_NUMBER_STUS :
1260 
1261 		if ( strncmp( pBuf, TS_JJY01_REPLY_STUS_ADJUSTED,
1262 			     TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED ) == 0
1263 		  || strncmp( pBuf, TS_JJY01_REPLY_STUS_UNADJUSTED,
1264 			     TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED ) == 0 ) {
1265 			/* Good */
1266 		} else {
1267 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
1268 				  pBuf ) ;
1269 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1270 			up->bLineError = TRUE ;
1271 			return JJY_RECEIVE_ERROR ;
1272 		}
1273 
1274 		break ;
1275 
1276 	case TS_JJY01_COMMAND_NUMBER_DCST :
1277 
1278 		if ( strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID,
1279 			     TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0
1280 		  || strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID,
1281 			     TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) {
1282 			/* Good */
1283 		} else {
1284 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
1285 				  pBuf ) ;
1286 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1287 			up->bLineError = TRUE ;
1288 			return JJY_RECEIVE_ERROR ;
1289 		}
1290 
1291 		break ;
1292 
1293 	default : /*  Unexpected reply */
1294 
1295 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
1296 			  pBuf ) ;
1297 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1298 		up->bLineError = TRUE ;
1299 		return JJY_RECEIVE_ERROR ;
1300 
1301 	}
1302 
1303 	if ( up->iTimestampCount == 2 ) {
1304 		/* Process date and time */
1305 
1306 		if ( up->iTimestamp[1] - 2 <= up->iTimestamp[0]
1307 		  && up->iTimestamp[0]     <= up->iTimestamp[1] ) {
1308 			/* 3 commands (time,date,stim) was excuted in two seconds */
1309 			jjy_synctime( peer, pp, up ) ;
1310 			return JJY_RECEIVE_DONE ;
1311 		} else if ( up->iTimestamp[0] > up->iTimestamp[1] ) {
1312 			/* Over midnight, and date is unsure */
1313 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2,
1314 				  up->iTimestamp[0], up->iTimestamp[1] ) ;
1315 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
1316 			return JJY_RECEIVE_SKIP ;
1317 		} else {
1318 			/* Slow reply */
1319 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2,
1320 				  up->iTimestamp[0], up->iTimestamp[1] ) ;
1321 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1322 			up->bLineError = TRUE ;
1323 			return JJY_RECEIVE_ERROR ;
1324 		}
1325 
1326 	}
1327 
1328 	/* Issue next command */
1329 
1330 	if ( tristate_jjy01_command_sequence[up->iCommandSeq].command != NULL ) {
1331 		up->iCommandSeq ++ ;
1332 	}
1333 
1334 	if ( tristate_jjy01_command_sequence[up->iCommandSeq].command == NULL ) {
1335 		/* Command sequence completed */
1336 		return JJY_RECEIVE_DONE ;
1337 	}
1338 
1339 	pCmd =  tristate_jjy01_command_sequence[up->iCommandSeq].command ;
1340 	iCmdLen = tristate_jjy01_command_sequence[up->iCommandSeq].commandLength ;
1341 	if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
1342 		refclock_report ( peer, CEVNT_FAULT ) ;
1343 	}
1344 
1345 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
1346 
1347 	return JJY_RECEIVE_WAIT ;
1348 
1349 }
1350 
1351 /**************************************************************************************************/
1352 
1353 static void
1354 jjy_poll_tristate_jjy01  ( int unit, struct peer *peer )
1355 {
1356 #ifdef DEBUG
1357 	static const char *sFunctionName = "jjy_poll_tristate_jjy01" ;
1358 #endif
1359 
1360 	struct refclockproc *pp ;
1361 	struct jjyunit	    *up ;
1362 
1363 	const char *	pCmd ;
1364 	int 		iCmdLen ;
1365 
1366 	pp = peer->procptr;
1367 	up = pp->unitptr ;
1368 
1369 	up->bLineError = FALSE ;
1370 	up->iTimestampCount = 0 ;
1371 
1372 	if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
1373 		/* Skip "dcst" and "stus" commands */
1374 		up->iCommandSeq = 2 ;
1375 		up->iLineCount = 2 ;
1376 	}
1377 
1378 #ifdef DEBUG
1379 	if ( debug ) {
1380 		printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->iLineCount=%d\n",
1381 			sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
1382 			up->iLineCount ) ;
1383 	}
1384 #endif
1385 
1386 	/*
1387 	 * Send a first command
1388 	 */
1389 
1390 	up->iCommandSeq ++ ;
1391 
1392 	pCmd =  tristate_jjy01_command_sequence[up->iCommandSeq].command ;
1393 	iCmdLen = tristate_jjy01_command_sequence[up->iCommandSeq].commandLength ;
1394 	if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
1395 		refclock_report ( peer, CEVNT_FAULT ) ;
1396 	}
1397 
1398 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
1399 
1400 }
1401 
1402 /*################################################################################################*/
1403 /*################################################################################################*/
1404 /*##												##*/
1405 /*##    The C-DEX Co. Ltd. JJY receiver JST2000							##*/
1406 /*##												##*/
1407 /*##    server  127.127.40.X  mode 2								##*/
1408 /*##												##*/
1409 /*################################################################################################*/
1410 /*################################################################################################*/
1411 /*                                                                                                */
1412 /*  Command               Response                                  Remarks                       */
1413 /*  --------------------  ----------------------------------------  ----------------------------  */
1414 /*  <ENQ>1J<ETX>          <STX>JYYMMDD HHMMSSS<ETX>                 J is a fixed character        */
1415 /*                                                                                                */
1416 /*################################################################################################*/
1417 
1418 static struct jjyRawDataBreak cdex_jst2000_raw_break [ ] =
1419 {
1420 	{ "\x03", 1 }, { NULL, 0 }
1421 } ;
1422 
1423 /**************************************************************************************************/
1424 
1425 static int
1426 jjy_start_cdex_jst2000 ( int unit, struct peer *peer, struct jjyunit *up )
1427 {
1428 
1429 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: C-DEX Co. Ltd. JST2000" ) ;
1430 
1431 	up->unittype  = UNITTYPE_CDEX_JST2000 ;
1432 	up->linespeed = SPEED232_CDEX_JST2000 ;
1433 	up->linediscipline = LDISC_RAW ;
1434 
1435 	up->pRawBreak = cdex_jst2000_raw_break ;
1436 	up->bWaitBreakString = TRUE ;
1437 
1438 	up->bSkipCntrlCharOnly = FALSE ;
1439 
1440 	return 0 ;
1441 
1442 }
1443 
1444 /**************************************************************************************************/
1445 
1446 static int
1447 jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
1448 {
1449 
1450 	struct jjyunit      *up ;
1451 	struct refclockproc *pp ;
1452 	struct peer         *peer ;
1453 
1454 	char	*pBuf, sLog [ 100 ] ;
1455 	int 	iLen ;
1456 	int 	rc ;
1457 
1458 	/* Initialize pointers */
1459 
1460 	peer = rbufp->recv_peer ;
1461 	pp = peer->procptr ;
1462 	up = pp->unitptr ;
1463 
1464 	if ( up->linediscipline == LDISC_RAW ) {
1465 		pBuf = up->sTextBuf ;
1466 		iLen = up->iTextBufLen ;
1467 	} else {
1468 		pBuf = pp->a_lastcode ;
1469 		iLen = pp->lencode ;
1470 	}
1471 
1472 	DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_cdex_jst2000", iLen ) ;
1473 
1474 	/* Check expected reply */
1475 
1476 	if ( up->iCommandSeq != 1 ) {
1477 		/* Command sequence has not been started, or has been completed */
1478 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
1479 			  pBuf ) ;
1480 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1481 		up->bLineError = TRUE ;
1482 		return JJY_RECEIVE_ERROR ;
1483 	}
1484 
1485 	/* Wait until ETX comes */
1486 
1487 	if ( up->iLineBufLen < 17 || up->sLineBuf[up->iLineBufLen-1] != 0x03 ) {
1488 		return JJY_RECEIVE_UNPROCESS ;
1489 	}
1490 
1491 	/* Check reply length */
1492 
1493 	if ( iLen != 15 ) {
1494 		/* Unexpected reply length */
1495 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
1496 			  iLen ) ;
1497 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1498 		up->bLineError = TRUE ;
1499 		return JJY_RECEIVE_ERROR ;
1500 	}
1501 
1502 	/* JYYMMDD HHMMSSS */
1503 
1504 	rc = sscanf ( pBuf, "J%2d%2d%2d %2d%2d%2d%1d",
1505 		      &up->year, &up->month, &up->day,
1506 		      &up->hour, &up->minute, &up->second,
1507 		      &up->msecond ) ;
1508 
1509 	if ( rc != 7 || up->month < 1 || up->month > 12 ||
1510 	     up->day < 1 || up->day > 31 || up->hour > 23 ||
1511 	     up->minute > 59 || up->second > 60 ) {
1512 		/* Invalid date and time */
1513 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
1514 			  rc, up->year, up->month, up->day,
1515 			  up->hour, up->minute, up->second ) ;
1516 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1517 		up->bLineError = TRUE ;
1518 		return JJY_RECEIVE_ERROR ;
1519 	}
1520 
1521 	up->year    += 2000 ;
1522 	up->msecond *= 100 ;
1523 
1524 	jjy_synctime( peer, pp, up ) ;
1525 
1526 	return JJY_RECEIVE_DONE ;
1527 
1528 }
1529 
1530 /**************************************************************************************************/
1531 
1532 static void
1533 jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
1534 {
1535 
1536 	struct refclockproc *pp ;
1537 	struct jjyunit      *up ;
1538 
1539 	pp = peer->procptr ;
1540 	up = pp->unitptr ;
1541 
1542 	up->bLineError = FALSE ;
1543 	up->iRawBufLen = 0 ;
1544 	up->iLineBufLen = 0 ;
1545 	up->iTextBufLen = 0 ;
1546 
1547 	/*
1548 	 * Send "<ENQ>1J<ETX>" command
1549 	 */
1550 
1551 	up->iCommandSeq ++ ;
1552 
1553 	if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4  ) {
1554 		refclock_report ( peer, CEVNT_FAULT ) ;
1555 	}
1556 
1557 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, "\0051J\003" ) ;
1558 
1559 }
1560 
1561 /*################################################################################################*/
1562 /*################################################################################################*/
1563 /*##												##*/
1564 /*##    The Echo Keisokuki Co. Ltd. JJY receiver LT2000						##*/
1565 /*##												##*/
1566 /*##    server  127.127.40.X  mode 3								##*/
1567 /*##												##*/
1568 /*################################################################################################*/
1569 /*################################################################################################*/
1570 /*                                                                                                */
1571 /*  Command               Response                                  Remarks                       */
1572 /*  --------------------  ----------------------------------------  ----------------------------  */
1573 /*  #                                                               Mode 1 ( Request & Send )     */
1574 /*  T                     YYMMDDWHHMMSS<BCC1><BCC2><CR>                                           */
1575 /*  C                                                               Mode 2 ( Continuous )         */
1576 /*                        YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR>     0.5 sec before time stamp     */
1577 /*                        <SUB>                                     Second signal                 */
1578 /*                                                                                                */
1579 /*################################################################################################*/
1580 
1581 #define	ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND		1
1582 #define	ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS		2
1583 #define	ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS	3
1584 
1585 #define	ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND 	"#"
1586 #define	ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_TIME 	"T"
1587 #define	ECHOKEISOKUKI_LT2000_COMMAND_CONTINUOUS 	"C"
1588 
1589 /**************************************************************************************************/
1590 
1591 static int
1592 jjy_start_echokeisokuki_lt2000 ( int unit, struct peer *peer, struct jjyunit *up )
1593 {
1594 
1595 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Echo Keisokuki Co. Ltd. LT2000" ) ;
1596 
1597 	up->unittype  = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
1598 	up->linespeed = SPEED232_ECHOKEISOKUKI_LT2000 ;
1599 	up->linediscipline = LDISC_CLK ;
1600 
1601 	up->operationmode = ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ;
1602 
1603 	return 0 ;
1604 
1605 }
1606 
1607 /**************************************************************************************************/
1608 
1609 static int
1610 jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
1611 {
1612 
1613 	struct jjyunit      *up ;
1614 	struct refclockproc *pp ;
1615 	struct peer	    *peer;
1616 
1617 	char	*pBuf, sLog [ 100 ], sErr [ 60 ] ;
1618 	int 	iLen ;
1619 	int 	rc ;
1620 	int	i, ibcc, ibcc1, ibcc2 ;
1621 
1622 	/* Initialize pointers */
1623 
1624 	peer = rbufp->recv_peer ;
1625 	pp = peer->procptr ;
1626 	up = pp->unitptr ;
1627 
1628 	if ( up->linediscipline == LDISC_RAW ) {
1629 		pBuf = up->sTextBuf ;
1630 		iLen = up->iTextBufLen ;
1631 	} else {
1632 		pBuf = pp->a_lastcode ;
1633 		iLen = pp->lencode ;
1634 	}
1635 
1636 	DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_echokeisokuki_lt2000", iLen ) ;
1637 
1638 	/* Check reply length */
1639 
1640 	if ( ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND
1641 	       && iLen != 15 )
1642 	  || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS
1643 	       && iLen != 17 )
1644 	  || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS
1645 	       && iLen != 17 ) ) {
1646 		/* Unexpected reply length */
1647 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
1648 			  iLen ) ;
1649 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1650 		up->bLineError = TRUE ;
1651 		return JJY_RECEIVE_ERROR ;
1652 	}
1653 
1654 	if ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND && iLen == 15 ) {
1655 		/* YYMMDDWHHMMSS<BCC1><BCC2> */
1656 
1657 		for ( i = ibcc = 0 ; i < 13 ; i ++ ) {
1658 			ibcc ^= pBuf[i] ;
1659 		}
1660 
1661 		ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
1662 		ibcc2 = 0x30 | ( ( ibcc      ) & 0xF ) ;
1663 		if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
1664 			snprintf( sErr, sizeof(sErr)-1, " BCC error : Recv=%02X,%02X / Calc=%02X,%02X ",
1665 				  pBuf[13] & 0xFF, pBuf[14] & 0xFF,
1666 				  ibcc1, ibcc2 ) ;
1667 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
1668 				  sErr ) ;
1669 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1670 			up->bLineError = TRUE ;
1671 			return JJY_RECEIVE_ERROR ;
1672 		}
1673 
1674 	}
1675 
1676 	if ( ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND
1677 	       && iLen == 15 )
1678 	  || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS
1679 	       && iLen == 17 )
1680 	  || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS
1681 	       && iLen == 17 ) ) {
1682 		/* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
1683 
1684 		rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
1685 			      &up->year, &up->month, &up->day,
1686 			      &up->hour, &up->minute, &up->second ) ;
1687 
1688 		if ( rc != 6 || up->month < 1 || up->month > 12
1689 		  || up->day < 1 || up->day > 31
1690 		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
1691 			/* Invalid date and time */
1692 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
1693 				  rc, up->year, up->month, up->day,
1694 				  up->hour, up->minute, up->second ) ;
1695 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1696 			up->bLineError = TRUE ;
1697 			return JJY_RECEIVE_ERROR ;
1698 		}
1699 
1700 		up->year += 2000 ;
1701 
1702 		if ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS
1703 		  || up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ) {
1704 			/* A time stamp comes on every 0.5 second in the mode 2 of the LT-2000. */
1705 
1706 			up->msecond = 500 ;
1707 			up->second -- ;
1708 			if ( up->second < 0 ) {
1709 				up->second = 59 ;
1710 				up->minute -- ;
1711 				if ( up->minute < 0 ) {
1712 					up->minute = 59 ;
1713 					up->hour -- ;
1714 					if ( up->hour < 0 ) {
1715 						up->hour = 23 ;
1716 						up->day -- ;
1717 						if ( up->day < 1 ) {
1718 							up->month -- ;
1719 							if ( up->month < 1 ) {
1720 								up->month = 12 ;
1721 								up->year -- ;
1722 							}
1723 						}
1724 					}
1725 				}
1726 			}
1727 
1728 		}
1729 
1730 		jjy_synctime( peer, pp, up ) ;
1731 
1732 
1733 	}
1734 
1735 	if (up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ) {
1736 		/* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
1737 
1738 		iLen = strlen( ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND ) ;
1739 		if ( write ( pp->io.fd, ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND, iLen ) != iLen  ) {
1740 			refclock_report ( peer, CEVNT_FAULT ) ;
1741 		}
1742 
1743 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND ) ;
1744 
1745 	}
1746 
1747 	return JJY_RECEIVE_DONE ;
1748 
1749 }
1750 
1751 /**************************************************************************************************/
1752 
1753 static void
1754 jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
1755 {
1756 
1757 	struct refclockproc *pp ;
1758 	struct jjyunit      *up ;
1759 
1760 	char	sCmd[2] ;
1761 
1762 	pp = peer->procptr ;
1763 	up = pp->unitptr ;
1764 
1765 	up->bLineError = FALSE ;
1766 
1767 	/*
1768 	 * Send "T" or "C" command
1769 	 */
1770 
1771 	switch ( up->operationmode ) {
1772 	case ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND :
1773 		sCmd[0] = 'T' ;
1774 		break ;
1775 	case ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS :
1776 	case ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS :
1777 		sCmd[0] = 'C' ;
1778 		break ;
1779 	}
1780 	sCmd[1] = 0 ;
1781 
1782 	if ( write ( pp->io.fd, sCmd, 1 ) != 1  ) {
1783 		refclock_report ( peer, CEVNT_FAULT ) ;
1784 	}
1785 
1786 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, sCmd ) ;
1787 
1788 }
1789 
1790 /*################################################################################################*/
1791 /*################################################################################################*/
1792 /*##												##*/
1793 /*##    The CITIZEN T.I.C CO., LTD. JJY receiver JJY200						##*/
1794 /*##												##*/
1795 /*##    server  127.127.40.X  mode 4								##*/
1796 /*##												##*/
1797 /*################################################################################################*/
1798 /*################################################################################################*/
1799 /*                                                                                                */
1800 /*  Command               Response                                  Remarks                       */
1801 /*  --------------------  ----------------------------------------  ----------------------------  */
1802 /*                        'XX YY/MM/DD W HH:MM:SS<CR>               XX:OK|NG|ER  W:0(Mon)-6(Sun)  */
1803 /*                                                                                                */
1804 /*################################################################################################*/
1805 
1806 static int
1807 jjy_start_citizentic_jjy200 ( int unit, struct peer *peer, struct jjyunit *up )
1808 {
1809 
1810 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: CITIZEN T.I.C CO. LTD. JJY200" ) ;
1811 
1812 	up->unittype  = UNITTYPE_CITIZENTIC_JJY200 ;
1813 	up->linespeed = SPEED232_CITIZENTIC_JJY200 ;
1814 	up->linediscipline = LDISC_CLK ;
1815 
1816 	return 0 ;
1817 
1818 }
1819 
1820 /**************************************************************************************************/
1821 
1822 static int
1823 jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
1824 {
1825 
1826 	struct jjyunit		*up ;
1827 	struct refclockproc	*pp ;
1828 	struct peer		*peer;
1829 
1830 	char	*pBuf, sLog [ 100 ], sMsg [ 16 ] ;
1831 	int	iLen ;
1832 	int	rc ;
1833 	char	cApostrophe, sStatus[3] ;
1834 	int	iWeekday ;
1835 
1836 	/* Initialize pointers */
1837 
1838 	peer = rbufp->recv_peer ;
1839 	pp = peer->procptr ;
1840 	up = pp->unitptr ;
1841 
1842 	if ( up->linediscipline == LDISC_RAW ) {
1843 		pBuf = up->sTextBuf ;
1844 		iLen = up->iTextBufLen ;
1845 	} else {
1846 		pBuf = pp->a_lastcode ;
1847 		iLen = pp->lencode ;
1848 	}
1849 
1850 	DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_citizentic_jjy200", iLen ) ;
1851 
1852 	/*
1853 	 * JJY-200 sends a timestamp every second.
1854 	 * So, a timestamp is ignored unless it is right after polled.
1855 	 */
1856 
1857 	if ( up->iProcessState != JJY_PROCESS_STATE_RECEIVE ) {
1858 		return JJY_RECEIVE_SKIP ;
1859 	}
1860 
1861 	/* Check reply length */
1862 
1863 	if ( iLen != 23 ) {
1864 		/* Unexpected reply length */
1865 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
1866 			  iLen ) ;
1867 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1868 		up->bLineError = TRUE ;
1869 		return JJY_RECEIVE_ERROR ;
1870 	}
1871 
1872 	/* 'XX YY/MM/DD W HH:MM:SS<CR> */
1873 
1874 	rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
1875 		      &cApostrophe, sStatus,
1876 		      &up->year, &up->month, &up->day, &iWeekday,
1877 		      &up->hour, &up->minute, &up->second ) ;
1878 	sStatus[2] = 0 ;
1879 
1880 	if ( rc != 9 || cApostrophe != '\''
1881 	  || ( strcmp( sStatus, "OK" ) != 0
1882 	    && strcmp( sStatus, "NG" ) != 0
1883 	    && strcmp( sStatus, "ER" ) != 0 )
1884 	  || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
1885 	  || iWeekday > 6
1886 	  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
1887 		/* Invalid date and time */
1888 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
1889 			  rc, up->year, up->month, up->day,
1890 			  up->hour, up->minute, up->second ) ;
1891 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
1892 		up->bLineError = TRUE ;
1893 		return JJY_RECEIVE_ERROR ;
1894 	} else if ( strcmp( sStatus, "NG" ) == 0
1895 		 || strcmp( sStatus, "ER" ) == 0 ) {
1896 		/* Timestamp is unsure */
1897 		snprintf( sMsg, sizeof(sMsg)-1, "status=%s", sStatus ) ;
1898 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TIMESTAMP_UNSURE,
1899 			  sMsg ) ;
1900 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ;
1901 		return JJY_RECEIVE_SKIP ;
1902 	}
1903 
1904 	up->year += 2000 ;
1905 	up->msecond = 0 ;
1906 
1907 	jjy_synctime( peer, pp, up ) ;
1908 
1909 	return JJY_RECEIVE_DONE ;
1910 
1911 }
1912 
1913 /**************************************************************************************************/
1914 
1915 static void
1916 jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
1917 {
1918 
1919 	struct refclockproc *pp ;
1920 	struct jjyunit	    *up ;
1921 
1922 	pp = peer->procptr ;
1923 	up = pp->unitptr ;
1924 
1925 	up->bLineError = FALSE ;
1926 
1927 }
1928 
1929 /*################################################################################################*/
1930 /*################################################################################################*/
1931 /*##												##*/
1932 /*##    The Tristate Ltd. GPS clock TS-GPS01							##*/
1933 /*##												##*/
1934 /*##    server  127.127.40.X  mode 5								##*/
1935 /*##												##*/
1936 /*################################################################################################*/
1937 /*################################################################################################*/
1938 /*                                                                                                */
1939 /*  This clock has NMEA mode and command/respose mode.                                            */
1940 /*  When this jjy driver are used, set to command/respose mode of this clock                      */
1941 /*  by the onboard switch SW4, and make sure the LED-Y is tured on.                               */
1942 /*  Other than this JJY driver, the refclock driver type 20, generic NMEA driver,                 */
1943 /*  works with the NMEA mode of this clock.                                                       */
1944 /*                                                                                                */
1945 /*  Command               Response                                  Remarks                       */
1946 /*  --------------------  ----------------------------------------  ----------------------------  */
1947 /*  stus<CR><LF>          *R|*G|*U|+U<CR><LF>                                                     */
1948 /*  date<CR><LF>          YY/MM/DD<CR><LF>                                                        */
1949 /*  time<CR><LF>          HH:MM:SS<CR><LF>                                                        */
1950 /*                                                                                                */
1951 /*################################################################################################*/
1952 
1953 #define	TS_GPS01_COMMAND_NUMBER_DATE	1
1954 #define	TS_GPS01_COMMAND_NUMBER_TIME	2
1955 #define	TS_GPS01_COMMAND_NUMBER_STUS	4
1956 
1957 #define	TS_GPS01_REPLY_DATE		"yyyy/mm/dd"
1958 #define	TS_GPS01_REPLY_TIME		"hh:mm:ss"
1959 #define	TS_GPS01_REPLY_STUS_RTC		"*R"
1960 #define	TS_GPS01_REPLY_STUS_GPS		"*G"
1961 #define	TS_GPS01_REPLY_STUS_UTC		"*U"
1962 #define	TS_GPS01_REPLY_STUS_PPS		"+U"
1963 
1964 #define	TS_GPS01_REPLY_LENGTH_DATE	    10	/* Length without <CR><LF> */
1965 #define	TS_GPS01_REPLY_LENGTH_TIME	    8	/* Length without <CR><LF> */
1966 #define	TS_GPS01_REPLY_LENGTH_STUS	    2	/* Length without <CR><LF> */
1967 
1968 static  struct
1969 {
1970 	char	commandNumber ;
1971 	const char	*command ;
1972 	int	commandLength ;
1973 	int	iExpectedReplyLength ;
1974 } tristate_gps01_command_sequence[] =
1975 {
1976 	{ 0, NULL, 0, 0 }, /* Idle */
1977 	{ TS_GPS01_COMMAND_NUMBER_STUS, "stus\r\n", 6, TS_GPS01_REPLY_LENGTH_STUS },
1978 	{ TS_GPS01_COMMAND_NUMBER_TIME, "time\r\n", 6, TS_GPS01_REPLY_LENGTH_TIME },
1979 	{ TS_GPS01_COMMAND_NUMBER_DATE, "date\r\n", 6, TS_GPS01_REPLY_LENGTH_DATE },
1980 	{ TS_GPS01_COMMAND_NUMBER_TIME, "time\r\n", 6, TS_GPS01_REPLY_LENGTH_TIME },
1981 	/* End of command */
1982 	{ 0, NULL, 0, 0 }
1983 } ;
1984 
1985 /**************************************************************************************************/
1986 
1987 static int
1988 jjy_start_tristate_gpsclock01 ( int unit, struct peer *peer, struct jjyunit *up )
1989 {
1990 
1991 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Tristate Ltd. TS-GPS01" ) ;
1992 
1993 	up->unittype  = UNITTYPE_TRISTATE_GPSCLOCK01 ;
1994 	up->linespeed = SPEED232_TRISTATE_GPSCLOCK01 ;
1995 	up->linediscipline = LDISC_CLK ;
1996 
1997 	return 0 ;
1998 
1999 }
2000 
2001 /**************************************************************************************************/
2002 
2003 static int
2004 jjy_receive_tristate_gpsclock01 ( struct recvbuf *rbufp )
2005 {
2006 #ifdef DEBUG
2007 	static	const char	*sFunctionName = "jjy_receive_tristate_gpsclock01" ;
2008 #endif
2009 
2010 	struct jjyunit	    *up ;
2011 	struct refclockproc *pp ;
2012 	struct peer	    *peer;
2013 
2014 	char *		pBuf ;
2015 	char		sLog [ 100 ] ;
2016 	int 		iLen ;
2017 	int 		rc ;
2018 
2019 	const char *	pCmd ;
2020 	int 		iCmdLen ;
2021 
2022 	/* Initialize pointers */
2023 
2024 	peer = rbufp->recv_peer ;
2025 	pp = peer->procptr ;
2026 	up = pp->unitptr ;
2027 
2028 	if ( up->linediscipline == LDISC_RAW ) {
2029 		pBuf = up->sTextBuf ;
2030 		iLen = up->iTextBufLen ;
2031 	} else {
2032 		pBuf = pp->a_lastcode ;
2033 		iLen = pp->lencode ;
2034 	}
2035 
2036 	DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_tristate_gpsclock01", iLen ) ;
2037 
2038 	/* Ignore NMEA data stream */
2039 
2040 	if ( iLen > 5
2041 	  && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) {
2042 #ifdef DEBUG
2043 		if ( debug ) {
2044 			printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n",
2045 				sFunctionName, pBuf ) ;
2046 		}
2047 #endif
2048 		return JJY_RECEIVE_WAIT ;
2049 	}
2050 
2051 	/*
2052 	 * Skip command prompt '$Cmd>' from the TS-GPSclock-01
2053 	 */
2054 	if ( iLen == 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) {
2055 		return JJY_RECEIVE_WAIT ;
2056 	} else if ( iLen > 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) {
2057 		pBuf += 5 ;
2058 		iLen -= 5 ;
2059 	}
2060 
2061 	/*
2062 	 * Ignore NMEA data stream after command prompt
2063 	 */
2064 	if ( iLen > 5
2065 	  && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) {
2066 #ifdef DEBUG
2067 		if ( debug ) {
2068 			printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n",
2069 				sFunctionName, pBuf ) ;
2070 		}
2071 #endif
2072 		return JJY_RECEIVE_WAIT ;
2073 	}
2074 
2075 	/* Check expected reply */
2076 
2077 	if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) {
2078 		/* Command sequence has not been started, or has been completed */
2079 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
2080 			  pBuf ) ;
2081 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2082 		up->bLineError = TRUE ;
2083 		return JJY_RECEIVE_ERROR ;
2084 	}
2085 
2086 	/* Check reply length */
2087 
2088 	if ( iLen != tristate_gps01_command_sequence[up->iCommandSeq].iExpectedReplyLength ) {
2089 		/* Unexpected reply length */
2090 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
2091 			  iLen ) ;
2092 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2093 		up->bLineError = TRUE ;
2094 		return JJY_RECEIVE_ERROR ;
2095 	}
2096 
2097 	/* Parse reply */
2098 
2099 	switch ( tristate_gps01_command_sequence[up->iCommandSeq].commandNumber ) {
2100 
2101 	case TS_GPS01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD */
2102 
2103 		rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
2104 
2105 		if ( rc != 3 || up->year < 2000 || 2099 <= up->year
2106 		  || up->month < 1 || 12 < up->month
2107 		  || up->day < 1 || 31 < up->day ) {
2108 			/* Invalid date */
2109 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE,
2110 				  rc, up->year, up->month, up->day ) ;
2111 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2112 			up->bLineError = TRUE ;
2113 			return JJY_RECEIVE_ERROR ;
2114 		}
2115 
2116 		break ;
2117 
2118 	case TS_GPS01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
2119 
2120 		if ( up->iTimestampCount >= 2 ) {
2121 			/* Too many time reply */
2122 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY,
2123 				  up->iTimestampCount ) ;
2124 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2125 			up->bLineError = TRUE ;
2126 			return JJY_RECEIVE_ERROR ;
2127 		}
2128 
2129 		rc = sscanf ( pBuf, "%2d:%2d:%2d",
2130 			      &up->hour, &up->minute, &up->second ) ;
2131 
2132 		if ( rc != 3
2133 		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
2134 			/* Invalid time */
2135 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
2136 				  rc, up->hour, up->minute, up->second ) ;
2137 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2138 			up->bLineError = TRUE ;
2139 			return JJY_RECEIVE_ERROR ;
2140 		}
2141 
2142 		up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ;
2143 
2144 		up->iTimestampCount++ ;
2145 
2146 		up->msecond = 0 ;
2147 
2148 		break ;
2149 
2150 	case TS_GPS01_COMMAND_NUMBER_STUS :
2151 
2152 		if ( strncmp( pBuf, TS_GPS01_REPLY_STUS_RTC, TS_GPS01_REPLY_LENGTH_STUS ) == 0
2153 		  || strncmp( pBuf, TS_GPS01_REPLY_STUS_GPS, TS_GPS01_REPLY_LENGTH_STUS ) == 0
2154 		  || strncmp( pBuf, TS_GPS01_REPLY_STUS_UTC, TS_GPS01_REPLY_LENGTH_STUS ) == 0
2155 		  || strncmp( pBuf, TS_GPS01_REPLY_STUS_PPS, TS_GPS01_REPLY_LENGTH_STUS ) == 0 ) {
2156 			/* Good */
2157 		} else {
2158 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
2159 				  pBuf ) ;
2160 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2161 			up->bLineError = TRUE ;
2162 			return JJY_RECEIVE_ERROR ;
2163 		}
2164 
2165 		break ;
2166 
2167 	default : /*  Unexpected reply */
2168 
2169 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
2170 			  pBuf ) ;
2171 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2172 		up->bLineError = TRUE ;
2173 		return JJY_RECEIVE_ERROR ;
2174 
2175 	}
2176 
2177 	if ( up->iTimestampCount == 2 ) {
2178 		/* Process date and time */
2179 
2180 		if ( up->iTimestamp[1] - 2 <= up->iTimestamp[0]
2181 		  && up->iTimestamp[0]     <= up->iTimestamp[1] ) {
2182 			/* 3 commands (time,date,stim) was excuted in two seconds */
2183 			jjy_synctime( peer, pp, up ) ;
2184 			return JJY_RECEIVE_DONE ;
2185 		} else if ( up->iTimestamp[0] > up->iTimestamp[1] ) {
2186 			/* Over midnight, and date is unsure */
2187 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2,
2188 				  up->iTimestamp[0], up->iTimestamp[1] ) ;
2189 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
2190 			return JJY_RECEIVE_SKIP ;
2191 		} else {
2192 			/* Slow reply */
2193 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2,
2194 				  up->iTimestamp[0], up->iTimestamp[1] ) ;
2195 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2196 			up->bLineError = TRUE ;
2197 			return JJY_RECEIVE_ERROR ;
2198 		}
2199 
2200 	}
2201 
2202 	if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) {
2203 		/* Command sequence completed */
2204 		jjy_synctime( peer, pp, up ) ;
2205 		return JJY_RECEIVE_DONE ;
2206 	}
2207 
2208 	/* Issue next command */
2209 
2210 	if ( tristate_gps01_command_sequence[up->iCommandSeq].command != NULL ) {
2211 		up->iCommandSeq ++ ;
2212 	}
2213 
2214 	if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) {
2215 		/* Command sequence completed */
2216 		up->iProcessState = JJY_PROCESS_STATE_DONE ;
2217 		return JJY_RECEIVE_DONE ;
2218 	}
2219 
2220 	pCmd =  tristate_gps01_command_sequence[up->iCommandSeq].command ;
2221 	iCmdLen = tristate_gps01_command_sequence[up->iCommandSeq].commandLength ;
2222 	if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
2223 		refclock_report ( peer, CEVNT_FAULT ) ;
2224 	}
2225 
2226 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
2227 
2228 	return JJY_RECEIVE_WAIT ;
2229 
2230 }
2231 
2232 /**************************************************************************************************/
2233 
2234 static void
2235 jjy_poll_tristate_gpsclock01 ( int unit, struct peer *peer )
2236 {
2237 #ifdef DEBUG
2238 	static const char *sFunctionName = "jjy_poll_tristate_gpsclock01" ;
2239 #endif
2240 
2241 	struct refclockproc *pp ;
2242 	struct jjyunit	    *up ;
2243 
2244 	const char *	pCmd ;
2245 	int		iCmdLen ;
2246 
2247 	pp = peer->procptr ;
2248 	up = pp->unitptr ;
2249 
2250 	up->iTimestampCount = 0 ;
2251 
2252 	if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
2253 		/* Skip "stus" command */
2254 		up->iCommandSeq = 1 ;
2255 		up->iLineCount = 1 ;
2256 	}
2257 
2258 #ifdef DEBUG
2259 	if ( debug ) {
2260 		printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->iLineCount=%d\n",
2261 			sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
2262 			up->iLineCount ) ;
2263 	}
2264 #endif
2265 
2266 	/*
2267 	 * Send a first command
2268 	 */
2269 
2270 	up->iCommandSeq ++ ;
2271 
2272 	pCmd =  tristate_gps01_command_sequence[up->iCommandSeq].command ;
2273 	iCmdLen = tristate_gps01_command_sequence[up->iCommandSeq].commandLength ;
2274 	if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
2275 		refclock_report ( peer, CEVNT_FAULT ) ;
2276 	}
2277 
2278 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
2279 
2280 }
2281 
2282 /*################################################################################################*/
2283 /*################################################################################################*/
2284 /*##												##*/
2285 /*##    The SEIKO TIME SYSTEMS TDC-300								##*/
2286 /*##												##*/
2287 /*##    server  127.127.40.X  mode 6								##*/
2288 /*##												##*/
2289 /*################################################################################################*/
2290 /*################################################################################################*/
2291 /*                                                                                                */
2292 /*  Type                  Response                                  Remarks                       */
2293 /*  --------------------  ----------------------------------------  ----------------------------  */
2294 /*  Type 1                <STX>HH:MM:SS<ETX>                                                      */
2295 /*  Type 2                <STX>YYMMDDHHMMSSWLSCU<ETX>               W:0(Sun)-6(Sat)               */
2296 /*  Type 3                <STX>YYMMDDWHHMMSS<ETX>                   W:0(Sun)-6(Sat)               */
2297 /*                        <STX><xE5><ETX>                           5 to 10 mSec. before second   */
2298 /*                                                                                                */
2299 /*################################################################################################*/
2300 
2301 static struct jjyRawDataBreak seiko_tsys_tdc_300_raw_break [ ] =
2302 {
2303 	{ "\x03", 1 }, { NULL, 0 }
2304 } ;
2305 
2306 /**************************************************************************************************/
2307 
2308 static int
2309 jjy_start_seiko_tsys_tdc_300 ( int unit, struct peer *peer, struct jjyunit *up )
2310 {
2311 
2312 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: SEIKO TIME SYSTEMS TDC-300" ) ;
2313 
2314 	up->unittype  = UNITTYPE_SEIKO_TIMESYS_TDC_300 ;
2315 	up->linespeed = SPEED232_SEIKO_TIMESYS_TDC_300 ;
2316 	up->linediscipline = LDISC_RAW ;
2317 
2318 	up->pRawBreak = seiko_tsys_tdc_300_raw_break ;
2319 	up->bWaitBreakString = TRUE ;
2320 
2321 	up->bSkipCntrlCharOnly = FALSE ;
2322 
2323 	return 0 ;
2324 
2325 }
2326 
2327 /**************************************************************************************************/
2328 
2329 static int
2330 jjy_receive_seiko_tsys_tdc_300 ( struct recvbuf *rbufp )
2331 {
2332 
2333 	struct peer		*peer;
2334 	struct refclockproc	*pp ;
2335 	struct jjyunit		*up ;
2336 
2337 	char	*pBuf, sLog [ 100 ] ;
2338 	int	iLen, i ;
2339 	int	rc, iWeekday ;
2340 	time_t	now ;
2341 	struct	tm	*pTime ;
2342 
2343 	/* Initialize pointers */
2344 
2345 	peer = rbufp->recv_peer ;
2346 	pp = peer->procptr ;
2347 	up = pp->unitptr ;
2348 
2349 	if ( up->linediscipline == LDISC_RAW ) {
2350 		pBuf = up->sTextBuf ;
2351 		iLen = up->iTextBufLen ;
2352 	} else {
2353 		pBuf = pp->a_lastcode ;
2354 		iLen = pp->lencode ;
2355 	}
2356 
2357 	DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_seiko_tsys_tdc_300", iLen ) ;
2358 
2359 	/*
2360 	 * TDC-300 sends a timestamp every second.
2361 	 * So, a timestamp is ignored unless it is right after polled.
2362 	 */
2363 
2364 	if ( up->iProcessState != JJY_PROCESS_STATE_RECEIVE ) {
2365 		return JJY_RECEIVE_SKIP ;
2366 	}
2367 
2368 	/* Process timestamp */
2369 
2370 	up->iReceiveSeq ++ ;
2371 
2372 	switch ( iLen ) {
2373 
2374 	case 8 : /* Type 1 : <STX>HH:MM:SS<ETX> */
2375 
2376 		for ( i = 0 ; i < iLen ; i ++ ) {
2377 			pBuf[i] &= 0x7F ;
2378 		}
2379 
2380 		rc = sscanf ( pBuf+1, "%2d:%2d:%2d",
2381 		      &up->hour, &up->minute, &up->second ) ;
2382 
2383 		if ( rc != 3
2384 		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
2385 			/* Invalid time */
2386 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
2387 				  rc, up->hour, up->minute, up->second ) ;
2388 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2389 			up->bLineError = TRUE ;
2390 			return JJY_RECEIVE_ERROR ;
2391 		} else if ( up->hour == 23 && up->minute == 59 && up->second >= 55 ) {
2392 			/* Uncertainty date guard */
2393 			return JJY_RECEIVE_WAIT ;
2394 		}
2395 
2396 		time( &now ) ;
2397 		pTime = localtime( &now ) ;
2398 		up->year  = pTime->tm_year ;
2399 		up->month = pTime->tm_mon + 1 ;
2400 		up->day   = pTime->tm_mday ;
2401 
2402 		break ;
2403 
2404 	case 17 : /* Type 2 : <STX>YYMMDDHHMMSSWLSCU<ETX> */
2405 
2406 		for ( i = 0 ; i < iLen ; i ++ ) {
2407 			pBuf[i] &= 0x7F ;
2408 		}
2409 
2410 		rc = sscanf ( pBuf+1, "%2d%2d%2d%2d%2d%2d%1d",
2411 		      &up->year, &up->month, &up->day,
2412 		      &up->hour, &up->minute, &up->second, &iWeekday ) ;
2413 
2414 		if ( rc != 7
2415 		  || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
2416 		  || iWeekday > 6
2417 		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
2418 			/* Invalid date and time */
2419 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
2420 				  rc, up->year, up->month, up->day,
2421 				  up->hour, up->minute, up->second ) ;
2422 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2423 			up->bLineError = TRUE ;
2424 			return JJY_RECEIVE_ERROR ;
2425 		}
2426 
2427 		break ;
2428 
2429 	case 13 : /* Type 3 : <STX>YYMMDDWHHMMSS<ETX> */
2430 
2431 		rc = sscanf ( pBuf, "%2d%2d%2d%1d%2d%2d%2d",
2432 		      &up->year, &up->month, &up->day, &iWeekday,
2433 		      &up->hour, &up->minute, &up->second ) ;
2434 
2435 		if ( rc != 7
2436 		  || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
2437 		  || iWeekday > 6
2438 		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
2439 			/* Invalid date and time */
2440 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
2441 				  rc, up->year, up->month, up->day,
2442 				  up->hour, up->minute, up->second ) ;
2443 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2444 			up->bLineError = TRUE ;
2445 			return JJY_RECEIVE_ERROR ;
2446 		}
2447 
2448 		return JJY_RECEIVE_WAIT ;
2449 
2450 	case 1 : /* Type 3 : <STX><xE5><ETX> */
2451 
2452 		if ( ( *pBuf & 0xFF ) != 0xE5 ) {
2453 			/* Invalid second signal */
2454 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
2455 				  up->sLineBuf ) ;
2456 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2457 			up->bLineError = TRUE ;
2458 			return JJY_RECEIVE_ERROR ;
2459 		} else if ( up->iReceiveSeq == 1 ) {
2460 			/* Wait for next timestamp */
2461 			up->iReceiveSeq -- ;
2462 			return JJY_RECEIVE_WAIT ;
2463 		} else if ( up->iReceiveSeq >= 3 ) {
2464 			/* Unexpected second signal */
2465 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
2466 				  up->sLineBuf ) ;
2467 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2468 			up->bLineError = TRUE ;
2469 			return JJY_RECEIVE_ERROR ;
2470 		}
2471 
2472 		break ;
2473 
2474 	default : /* Unexpected reply length */
2475 
2476 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
2477 			  iLen ) ;
2478 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
2479 		up->bLineError = TRUE ;
2480 		return JJY_RECEIVE_ERROR ;
2481 
2482 	}
2483 
2484 	up->year += 2000 ;
2485 	up->msecond = 0 ;
2486 
2487 	jjy_synctime( peer, pp, up ) ;
2488 
2489 	return JJY_RECEIVE_DONE ;
2490 
2491 }
2492 
2493 /**************************************************************************************************/
2494 
2495 static void
2496 jjy_poll_seiko_tsys_tdc_300 ( int unit, struct peer *peer )
2497 {
2498 
2499 	struct refclockproc *pp ;
2500 	struct jjyunit	    *up ;
2501 
2502 	pp = peer->procptr ;
2503 	up = pp->unitptr ;
2504 
2505 	up->bLineError = FALSE ;
2506 
2507 }
2508 
2509 /*################################################################################################*/
2510 /*################################################################################################*/
2511 /*##												##*/
2512 /*##    Telephone JJY										##*/
2513 /*##												##*/
2514 /*##    server  127.127.40.X  mode 100 to 180							##*/
2515 /*##												##*/
2516 /*################################################################################################*/
2517 /*################################################################################################*/
2518 /*                                                                                                */
2519 /*  Prompt                Command               Response              Remarks                     */
2520 /*  --------------------  --------------------  --------------------  --------------------------  */
2521 /*  Name<SP>?<SP>         TJJY<CR>              Welcome messages      TJJY is a guest user ID     */
2522 /*  >                     4DATE<CR>             YYYYMMDD<CR>                                      */
2523 /*  >                     LEAPSEC<CR>           XX<CR>                One of <SP>0, +1, -1        */
2524 /*  >                     TIME<CR>              HHMMSS<CR>            3 times on second           */
2525 /*  >                     BYE<CR>               Sayounara messages                                */
2526 /*                                                                                                */
2527 /*################################################################################################*/
2528 
2529 static struct jjyRawDataBreak teljjy_raw_break [ ] =
2530 {
2531 	{ "\r\n", 2 },
2532 	{ "\r"  , 1 },
2533 	{ "\n"  , 1 },
2534 	{ "Name ? ", 7 },
2535 	{ ">"   , 1 },
2536 	{ "+++" , 3 },
2537 	{ NULL  , 0 }
2538 } ;
2539 
2540 #define	TELJJY_STATE_IDLE	0
2541 #define	TELJJY_STATE_DAILOUT	1
2542 #define	TELJJY_STATE_LOGIN	2
2543 #define	TELJJY_STATE_CONNECT	3
2544 #define	TELJJY_STATE_BYE	4
2545 
2546 #define	TELJJY_EVENT_NULL	0
2547 #define	TELJJY_EVENT_START	1
2548 #define	TELJJY_EVENT_CONNECT	2
2549 #define	TELJJY_EVENT_DISCONNECT	3
2550 #define	TELJJY_EVENT_COMMAND	4
2551 #define	TELJJY_EVENT_LOGIN	5	/* Posted by the jjy_receive_telephone */
2552 #define	TELJJY_EVENT_PROMPT	6	/* Posted by the jjy_receive_telephone */
2553 #define	TELJJY_EVENT_DATA	7	/* Posted by the jjy_receive_telephone */
2554 #define	TELJJY_EVENT_ERROR	8	/* Posted by the jjy_receive_telephone */
2555 #define	TELJJY_EVENT_SILENT	9	/* Posted by the jjy_timer_telephone */
2556 #define	TELJJY_EVENT_TIMEOUT	10	/* Posted by the jjy_timer_telephone */
2557 
2558 static	void 	teljjy_control		( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2559 
2560 static	int 	teljjy_idle_ignore	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2561 static	int 	teljjy_idle_dialout	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2562 static	int 	teljjy_dial_ignore	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2563 static	int 	teljjy_dial_login	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2564 static	int 	teljjy_dial_disc	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2565 static	int 	teljjy_login_ignore	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2566 static	int 	teljjy_login_disc	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2567 static	int 	teljjy_login_conn	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2568 static	int 	teljjy_login_login	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2569 static	int 	teljjy_login_silent	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2570 static	int 	teljjy_login_error	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2571 static	int 	teljjy_conn_ignore	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2572 static	int 	teljjy_conn_disc	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2573 static	int 	teljjy_conn_send	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2574 static	int 	teljjy_conn_data	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2575 static	int 	teljjy_conn_silent	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2576 static	int 	teljjy_conn_error	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2577 static	int 	teljjy_bye_ignore	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2578 static	int 	teljjy_bye_disc 	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2579 static	int 	teljjy_bye_modem	( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
2580 
2581 static int ( *pTeljjyHandler [ ] [ 5 ] ) ( struct peer *, struct refclockproc *, struct jjyunit *) =
2582 {               	/*STATE_IDLE           STATE_DAILOUT       STATE_LOGIN           STATE_CONNECT       STATE_BYE        */
2583 /* NULL       */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore },
2584 /* START      */	{ teljjy_idle_dialout, teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore },
2585 /* CONNECT    */	{ teljjy_idle_ignore , teljjy_dial_login , teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore },
2586 /* DISCONNECT */	{ teljjy_idle_ignore , teljjy_dial_disc  , teljjy_login_disc  , teljjy_conn_disc  , teljjy_bye_disc   },
2587 /* COMMAND    */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_modem  },
2588 /* LOGIN      */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_login , teljjy_conn_error , teljjy_bye_ignore },
2589 /* PROMPT     */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_conn  , teljjy_conn_send  , teljjy_bye_ignore },
2590 /* DATA       */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_data  , teljjy_bye_ignore },
2591 /* ERROR      */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_error , teljjy_conn_error , teljjy_bye_ignore },
2592 /* SILENT     */	{ teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_silent, teljjy_conn_silent, teljjy_bye_ignore },
2593 /* TIMEOUT    */	{ teljjy_idle_ignore , teljjy_dial_disc  , teljjy_login_error , teljjy_conn_error , teljjy_bye_modem  }
2594 } ;
2595 
2596 static short iTeljjyNextState [ ] [ 5 ] =
2597 {               	/*STATE_IDLE            STATE_DAILOUT         STATE_LOGIN           STATE_CONNECT         STATE_BYE         */
2598 /* NULL       */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
2599 /* START      */	{ TELJJY_STATE_DAILOUT, TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
2600 /* CONNECT    */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_LOGIN  , TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
2601 /* DISCONNECT */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE },
2602 /* COMMAND    */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
2603 /* LOGIN      */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_BYE    , TELJJY_STATE_BYE  },
2604 /* PROMPT     */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_CONNECT, TELJJY_STATE_BYE    , TELJJY_STATE_BYE  },
2605 /* DATA       */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
2606 /* ERROR      */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_BYE    , TELJJY_STATE_BYE    , TELJJY_STATE_BYE  },
2607 /* SILENT     */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
2608 /* TIMEOUT    */	{ TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_BYE    , TELJJY_STATE_BYE    , TELJJY_STATE_BYE  }
2609 } ;
2610 
2611 static short iTeljjyPostEvent [ ] [ 5 ] =
2612 {               	/*STATE_IDLE         STATE_DAILOUT      STATE_LOGIN           STATE_CONNECT         STATE_BYE         */
2613 /* NULL       */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2614 /* START      */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2615 /* CONNECT    */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2616 /* DISCONNECT */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2617 /* COMMAND    */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2618 /* LOGIN      */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL },
2619 /* PROMPT     */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_PROMPT , TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL },
2620 /* DATA       */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2621 /* ERROR      */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_COMMAND, TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL },
2622 /* SILENT     */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
2623 /* TIMEOUT    */	{ TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_COMMAND, TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL }
2624 } ;
2625 
2626 static short iTeljjySilentTimeout [ 5 ] = { 0,   0, 10,  5,  0 } ;
2627 static short iTeljjyStateTimeout  [ 5 ] = { 0, 120, 60, 60, 40 } ;
2628 
2629 #define	TELJJY_STAY_CLOCK_STATE  	0
2630 #define	TELJJY_CHANGE_CLOCK_STATE	1
2631 
2632 /* Command and replay */
2633 
2634 #define	TELJJY_REPLY_NONE	0
2635 #define	TELJJY_REPLY_4DATE	1
2636 #define	TELJJY_REPLY_TIME	2
2637 #define	TELJJY_REPLY_LEAPSEC	3
2638 #define	TELJJY_REPLY_LOOP	4
2639 #define	TELJJY_REPLY_PROMPT	5
2640 #define	TELJJY_REPLY_LOOPBACK	6
2641 #define	TELJJY_REPLY_COM	7
2642 
2643 #define	TELJJY_COMMAND_START_SKIP_LOOPBACK	7
2644 
2645 static  struct
2646 {
2647 	const char	*command ;
2648 	int	commandLength ;
2649 	int	iEchobackReplyLength ;
2650 	int	iExpectedReplyType   ;
2651 	int	iExpectedReplyLength ;
2652 } teljjy_command_sequence[] =
2653 {
2654 	{ NULL, 0, 0, 0, 0 }, /* Idle */
2655 	{ "LOOP\r"   , 5, 4, TELJJY_REPLY_LOOP    , 0 }, /* Getting into loopback mode */
2656 	{ ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
2657 	{ ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
2658 	{ ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
2659 	{ ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
2660 	{ ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
2661 	{ "COM\r"    , 4, 3, TELJJY_REPLY_COM     , 0 }, /* Exit from loopback mode */
2662 	/* TELJJY_COMMAND_START_SKIP_LOOPBACK */
2663 	{ "TIME\r"   , 5, 4, TELJJY_REPLY_TIME    , 6 },
2664 	{ "4DATE\r"  , 6, 5, TELJJY_REPLY_4DATE   , 8 },
2665 	{ "LEAPSEC\r", 8, 7, TELJJY_REPLY_LEAPSEC , 2 },
2666 	{ "TIME\r"   , 5, 4, TELJJY_REPLY_TIME    , 6 },
2667 	{ "BYE\r"    , 4, 3, TELJJY_REPLY_NONE    , 0 },
2668 	/* End of command */
2669 	{ NULL, 0, 0, 0, 0 }
2670 } ;
2671 
2672 #define	TELJJY_LOOPBACK_DELAY_THRESHOLD		700 /* Milli second */
2673 
2674 #ifdef	DEBUG
2675 #define	DEBUG_TELJJY_PRINTF(sFunc)	{ if ( debug ) { printf ( "refclock_jjy.c : %s : iClockState=%d iClockEvent=%d iTeljjySilentTimer=%d iTeljjyStateTimer=%d iClockCommandSeq=%d\n", sFunc, up->iClockState, up->iClockEvent, up->iTeljjySilentTimer, up->iTeljjyStateTimer, up->iClockCommandSeq ) ; } }
2676 #else
2677 #define	DEBUG_TELJJY_PRINTF(sFunc)
2678 #endif
2679 
2680 /**************************************************************************************************/
2681 
2682 static int
2683 jjy_start_telephone ( int unit, struct peer *peer, struct jjyunit *up )
2684 {
2685 
2686 	char	sLog [ 80 ], sFirstThreeDigits [ 4 ] ;
2687 	int	i, iNumberOfDigitsOfPhoneNumber, iCommaCount, iCommaPosition ;
2688 	int	iFirstThreeDigitsCount ;
2689 
2690 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Telephone JJY" ) ;
2691 
2692 	up->unittype  = UNITTYPE_TELEPHONE ;
2693 	up->linespeed = SPEED232_TELEPHONE ;
2694 	up->linediscipline = LDISC_RAW ;
2695 
2696 	up->pRawBreak = teljjy_raw_break ;
2697 	up->bWaitBreakString = TRUE ;
2698 
2699 	up->bSkipCntrlCharOnly = TRUE ;
2700 
2701 	up->iClockState = TELJJY_STATE_IDLE ;
2702 	up->iClockEvent = TELJJY_EVENT_NULL ;
2703 
2704 	/* Check the telephone number */
2705 
2706 	if ( sys_phone[0] == NULL ) {
2707 		msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf must be specified." ) ;
2708 		up->bInitError = TRUE ;
2709 		return 1 ;
2710 	}
2711 
2712 	if ( sys_phone[1] != NULL ) {
2713 		msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be only one." ) ;
2714 		up->bInitError = TRUE ;
2715 		return 1 ;
2716 	}
2717 
2718 	iNumberOfDigitsOfPhoneNumber = iCommaCount = iCommaPosition = iFirstThreeDigitsCount = 0 ;
2719 	for ( i = 0 ; i < strlen( sys_phone[0] ) ; i ++ ) {
2720 		if ( isdigit( (u_char)sys_phone[0][i] ) ) {
2721 			if ( iFirstThreeDigitsCount < sizeof(sFirstThreeDigits)-1 ) {
2722 				sFirstThreeDigits[iFirstThreeDigitsCount++] = sys_phone[0][i] ;
2723 			}
2724 			iNumberOfDigitsOfPhoneNumber ++ ;
2725 		} else if ( sys_phone[0][i] == ',' ) {
2726 			iCommaCount ++ ;
2727 			if ( iCommaCount > 1 ) {
2728 				msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be zero or one comma." ) ;
2729 				up->bInitError = TRUE ;
2730 				return 1 ;
2731 			}
2732 			iFirstThreeDigitsCount = 0 ;
2733 			iCommaPosition = i ;
2734 		} else if ( sys_phone[0][i] != '-' ) {
2735 			msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be a number or a hyphen." ) ;
2736 			up->bInitError = TRUE ;
2737 			return 1 ;
2738 		}
2739 	}
2740 	sFirstThreeDigits[iFirstThreeDigitsCount] = 0 ;
2741 
2742 	if ( iCommaCount == 1 ) {
2743 		if ( iCommaPosition != 1 || *sys_phone[0] != '0' ) {
2744 			msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : Getting an outside line should be '0,'." ) ;
2745 			up->bInitError = TRUE ;
2746 			return 1 ;
2747 		}
2748 	}
2749 
2750 	if ( iNumberOfDigitsOfPhoneNumber - iCommaPosition < 6 || 10 < iNumberOfDigitsOfPhoneNumber - iCommaPosition ) {
2751 		/* Too short or too long */
2752 		msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone=%s : Number of digits should be 6 to 10.", sys_phone[0] ) ;
2753 		up->bInitError = TRUE ;
2754 		return 1 ;
2755 	}
2756 
2757 	if ( strncmp( sFirstThreeDigits + iCommaPosition, "00" , 2 ) == 0
2758 	  || strncmp( sFirstThreeDigits + iCommaPosition, "10" , 2 ) == 0
2759 	  || strncmp( sFirstThreeDigits + iCommaPosition, "11" , 2 ) == 0
2760 	  || strncmp( sFirstThreeDigits + iCommaPosition, "12" , 2 ) == 0
2761 	  || strncmp( sFirstThreeDigits + iCommaPosition, "171", 3 ) == 0
2762 	  || strncmp( sFirstThreeDigits + iCommaPosition, "177", 3 ) == 0
2763 	  || ( sFirstThreeDigits[0] == '0' &&  sFirstThreeDigits[2] == '0' ) ) {
2764 		/* Not allowed because of emergency numbers or special service numbers */
2765 		msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone=%s : First 2 or 3 digits are not allowed.", sys_phone[0] ) ;
2766 		up->bInitError = TRUE ;
2767 		return 1 ;
2768 	}
2769 
2770 	snprintf( sLog, sizeof(sLog), "phone=%s", sys_phone[0] ) ;
2771 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
2772 
2773 	if ( peer->minpoll < 8 ) {
2774 		/* minpoll must be greater or equal to 8 ( 256 seconds = about 4 minutes ) */
2775 		int oldminpoll = peer->minpoll ;
2776 		peer->minpoll = 8 ;
2777 		if ( peer->ppoll < peer->minpoll ) {
2778 			peer->ppoll = peer->minpoll ;
2779 		}
2780 		if ( peer->maxpoll < peer->minpoll ) {
2781 			peer->maxpoll = peer->minpoll ;
2782 		}
2783 		snprintf( sLog, sizeof(sLog), "minpoll=%d -> %d", oldminpoll, peer->minpoll ) ;
2784 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
2785 	}
2786 
2787 	return 0 ;
2788 
2789 }
2790 
2791 /**************************************************************************************************/
2792 
2793 static int
2794 jjy_receive_telephone ( struct recvbuf *rbufp )
2795 {
2796 #ifdef DEBUG
2797 	static	const char	*sFunctionName = "jjy_receive_telephone" ;
2798 #endif
2799 
2800 	struct	peer         *peer;
2801 	struct	refclockproc *pp ;
2802 	struct	jjyunit      *up ;
2803 	char	*pBuf ;
2804 	int	iLen ;
2805 	short	iPreviousModemState ;
2806 
2807 	peer = rbufp->recv_peer ;
2808 	pp = peer->procptr ;
2809 	up = pp->unitptr ;
2810 
2811 	DEBUG_TELJJY_PRINTF( sFunctionName ) ;
2812 
2813 	if ( up->iClockState == TELJJY_STATE_IDLE
2814 	  || up->iClockState == TELJJY_STATE_DAILOUT
2815 	  || up->iClockState == TELJJY_STATE_BYE ) {
2816 
2817 		iPreviousModemState = getModemState( up ) ;
2818 
2819 		modem_receive ( rbufp ) ;
2820 
2821 		if ( iPreviousModemState != up->iModemState ) {
2822 			/* Modem state is changed just now. */
2823 			if ( isModemStateDisconnect( up->iModemState ) ) {
2824 				up->iClockEvent = TELJJY_EVENT_DISCONNECT ;
2825 				teljjy_control ( peer, pp, up ) ;
2826 			} else if ( isModemStateConnect( up->iModemState ) ) {
2827 				up->iClockEvent = TELJJY_EVENT_CONNECT ;
2828 				teljjy_control ( peer, pp, up ) ;
2829 			}
2830 		}
2831 
2832 		return JJY_RECEIVE_WAIT ;
2833 
2834 	}
2835 
2836 	if ( up->linediscipline == LDISC_RAW ) {
2837 		pBuf = up->sTextBuf ;
2838 		iLen = up->iTextBufLen ;
2839 	} else {
2840 		pBuf = pp->a_lastcode ;
2841 		iLen = pp->lencode ;
2842 	}
2843 
2844 	up->iTeljjySilentTimer = 0 ;
2845 	if      ( iLen == 7 && strncmp( pBuf, "Name ? ", 7 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_LOGIN  ; }
2846 	else if ( iLen == 1 && strncmp( pBuf, ">"      , 1 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_PROMPT ; }
2847 	else if ( iLen >= 1 && strncmp( pBuf, "?"      , 1 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_ERROR  ; }
2848 	else                                                        { up->iClockEvent = TELJJY_EVENT_DATA   ; }
2849 
2850 	teljjy_control ( peer, pp, up ) ;
2851 
2852 	return JJY_RECEIVE_WAIT ;
2853 
2854 }
2855 
2856 /**************************************************************************************************/
2857 
2858 static void
2859 jjy_poll_telephone ( int unit, struct peer *peer )
2860 {
2861 #ifdef DEBUG
2862 	static const char *sFunctionName = "jjy_poll_telephone" ;
2863 #endif
2864 
2865 	struct	refclockproc *pp ;
2866 	struct	jjyunit      *up ;
2867 
2868 	pp = peer->procptr ;
2869 	up = pp->unitptr ;
2870 
2871 	DEBUG_TELJJY_PRINTF( sFunctionName ) ;
2872 
2873 	if ( up->iClockState == TELJJY_STATE_IDLE ) {
2874 		up->iRawBufLen = 0 ;
2875 		up->iLineBufLen = 0 ;
2876 		up->iTextBufLen = 0 ;
2877 	}
2878 
2879 	up->iClockEvent = TELJJY_EVENT_START ;
2880 	teljjy_control ( peer, pp, up ) ;
2881 
2882 }
2883 
2884 /**************************************************************************************************/
2885 
2886 static void
2887 jjy_timer_telephone ( int unit, struct peer *peer )
2888 {
2889 #ifdef DEBUG
2890 	static const char *sFunctionName = "jjy_timer_telephone" ;
2891 #endif
2892 
2893 	struct	refclockproc *pp ;
2894 	struct	jjyunit      *up ;
2895 	short	iPreviousModemState ;
2896 
2897 	pp = peer->procptr ;
2898 	up = pp->unitptr ;
2899 
2900 	DEBUG_TELJJY_PRINTF( sFunctionName ) ;
2901 
2902 	if ( iTeljjySilentTimeout[up->iClockState] != 0 ) {
2903 		up->iTeljjySilentTimer++ ;
2904 		if ( iTeljjySilentTimeout[up->iClockState] <= up->iTeljjySilentTimer ) {
2905 			up->iClockEvent = TELJJY_EVENT_SILENT ;
2906 			teljjy_control ( peer, pp, up ) ;
2907 		}
2908 	}
2909 
2910 	if ( iTeljjyStateTimeout[up->iClockState] != 0 ) {
2911 		up->iTeljjyStateTimer++ ;
2912 		if ( iTeljjyStateTimeout[up->iClockState] <= up->iTeljjyStateTimer ) {
2913 			up->iClockEvent = TELJJY_EVENT_TIMEOUT ;
2914 			teljjy_control ( peer, pp, up ) ;
2915 		}
2916 	}
2917 
2918 	if ( isModemStateTimerOn( up ) ) {
2919 
2920 		iPreviousModemState = getModemState( up ) ;
2921 
2922 		modem_timer ( unit, peer ) ;
2923 
2924 		if ( iPreviousModemState != up->iModemState ) {
2925 			/* Modem state is changed just now. */
2926 			if ( isModemStateDisconnect( up->iModemState ) ) {
2927 				up->iClockEvent = TELJJY_EVENT_DISCONNECT ;
2928 				teljjy_control ( peer, pp, up ) ;
2929 			} else if ( isModemStateConnect( up->iModemState ) ) {
2930 				up->iClockEvent = TELJJY_EVENT_CONNECT ;
2931 				teljjy_control ( peer, pp, up ) ;
2932 			}
2933 		}
2934 
2935 	}
2936 
2937 }
2938 
2939 /**************************************************************************************************/
2940 
2941 static void
2942 teljjy_control ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
2943 {
2944 
2945 	int	i, rc ;
2946 	short	iPostEvent = TELJJY_EVENT_NULL ;
2947 
2948 	DEBUG_TELJJY_PRINTF( "teljjy_control" ) ;
2949 
2950 	rc = (*pTeljjyHandler[up->iClockEvent][up->iClockState])( peer, pp, up ) ;
2951 
2952 	if ( rc == TELJJY_CHANGE_CLOCK_STATE ) {
2953 		iPostEvent = iTeljjyPostEvent[up->iClockEvent][up->iClockState] ;
2954 #ifdef DEBUG
2955 		if ( debug ) {
2956 			printf( "refclock_jjy.c : teljjy_control : iClockState=%hd -> %hd  iPostEvent=%hd\n",
2957 				up->iClockState, iTeljjyNextState[up->iClockEvent][up->iClockState], iPostEvent ) ;
2958 		}
2959 #endif
2960 		up->iTeljjySilentTimer = 0 ;
2961 		if ( up->iClockState != iTeljjyNextState[up->iClockEvent][up->iClockState] ) {
2962 			/* Telephone JJY state is changing now */
2963 			up->iTeljjyStateTimer = 0 ;
2964 			up->bLineError = FALSE ;
2965 			up->iClockCommandSeq = 0 ;
2966 			up->iTimestampCount = 0 ;
2967 			up->iLoopbackCount = 0 ;
2968 			for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) {
2969 				up->bLoopbackTimeout[i] = FALSE ;
2970 			}
2971 			if (iTeljjyNextState[up->iClockEvent][up->iClockState] == TELJJY_STATE_IDLE ) {
2972 				/* Telephone JJY state is changing to IDLE just now */
2973 				up->iProcessState = JJY_PROCESS_STATE_DONE ;
2974 			}
2975 		}
2976 		up->iClockState = iTeljjyNextState[up->iClockEvent][up->iClockState] ;
2977 
2978 	}
2979 
2980 	if ( iPostEvent != TELJJY_EVENT_NULL ) {
2981 		up->iClockEvent = iPostEvent ;
2982 		teljjy_control ( peer, pp, up ) ;
2983 	}
2984 
2985 	up->iClockEvent = TELJJY_EVENT_NULL ;
2986 
2987 }
2988 
2989 /**************************************************************************************************/
2990 
2991 static void
2992 teljjy_setDelay ( struct peer *peer, struct jjyunit *up )
2993 {
2994 
2995 	char	sLog [ 60 ] ;
2996 	int	milliSecond, microSecond ;
2997 
2998 	gettimeofday( &(up->delayTime[up->iLoopbackCount]), NULL ) ;
2999 
3000 	up->delayTime[up->iLoopbackCount].tv_sec  -= up->sendTime[up->iLoopbackCount].tv_sec ;
3001 	up->delayTime[up->iLoopbackCount].tv_usec -= up->sendTime[up->iLoopbackCount].tv_usec ;
3002 	if ( up->delayTime[up->iLoopbackCount].tv_usec < 0 ) {
3003 		up->delayTime[up->iLoopbackCount].tv_sec -- ;
3004 		up->delayTime[up->iLoopbackCount].tv_usec += 1000000 ;
3005 	}
3006 
3007 	milliSecond  = up->delayTime[up->iLoopbackCount].tv_usec / 1000 ;
3008 	microSecond  = up->delayTime[up->iLoopbackCount].tv_usec - milliSecond * 1000 ;
3009 	milliSecond += up->delayTime[up->iLoopbackCount].tv_sec * 1000 ;
3010 
3011 	snprintf( sLog, sizeof(sLog), JJY_CLOCKSTATS_MESSAGE_LOOPBACK_DELAY,
3012 		  milliSecond, microSecond ) ;
3013 
3014 	if ( milliSecond > TELJJY_LOOPBACK_DELAY_THRESHOLD ) {
3015 		/* Delay > 700 mS */
3016 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ;
3017 	} else {
3018 		/* Delay <= 700 mS */
3019 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
3020 	}
3021 
3022 }
3023 
3024 /**************************************************************************************************/
3025 
3026 static int
3027 teljjy_getDelay ( struct peer *peer, struct jjyunit *up )
3028 {
3029 
3030 	struct	timeval maxTime, minTime, averTime ;
3031 	int	i ;
3032 	int	minIndex = 0, maxIndex = 0, iAverCount = 0 ;
3033 	int	iThresholdSecond, iThresholdMicroSecond ;
3034 	int	iPercent ;
3035 
3036 	minTime.tv_sec = minTime.tv_usec = 0 ;
3037 	maxTime.tv_sec = maxTime.tv_usec = 0 ;
3038 
3039 	iThresholdSecond = TELJJY_LOOPBACK_DELAY_THRESHOLD / 1000 ;
3040 	iThresholdMicroSecond = ( TELJJY_LOOPBACK_DELAY_THRESHOLD - ( TELJJY_LOOPBACK_DELAY_THRESHOLD / 1000 ) * 1000 ) * 1000 ;
3041 
3042 	up->iLoopbackValidCount = 0 ;
3043 
3044 	for ( i = 0 ; i < MAX_LOOPBACK && i < up->iLoopbackCount ; i ++ ) {
3045 		if ( up->bLoopbackTimeout[i]
3046 		  || up->delayTime[i].tv_sec  > iThresholdSecond
3047 		|| ( up->delayTime[i].tv_sec == iThresholdSecond
3048 		  && up->delayTime[i].tv_usec > iThresholdMicroSecond ) ) {
3049 			continue ;
3050 		}
3051 		if ( up->iLoopbackValidCount == 0 ) {
3052 			minTime.tv_sec  = up->delayTime[i].tv_sec  ;
3053 			minTime.tv_usec = up->delayTime[i].tv_usec ;
3054 			maxTime.tv_sec  = up->delayTime[i].tv_sec  ;
3055 			maxTime.tv_usec = up->delayTime[i].tv_usec ;
3056 			minIndex = maxIndex = i ;
3057 		} else if ( minTime.tv_sec  > up->delayTime[i].tv_sec
3058 		       || ( minTime.tv_sec == up->delayTime[i].tv_sec
3059 		         && minTime.tv_usec > up->delayTime[i].tv_usec ) ) {
3060 			minTime.tv_sec  = up->delayTime[i].tv_sec  ;
3061 			minTime.tv_usec = up->delayTime[i].tv_usec ;
3062 			minIndex = i ;
3063 		} else if ( maxTime.tv_sec  < up->delayTime[i].tv_sec
3064 		       || ( maxTime.tv_sec == up->delayTime[i].tv_sec
3065 		         && maxTime.tv_usec < up->delayTime[i].tv_usec ) ) {
3066 			maxTime.tv_sec  = up->delayTime[i].tv_sec  ;
3067 			maxTime.tv_usec = up->delayTime[i].tv_usec ;
3068 			maxIndex = i ;
3069 		}
3070 		up->iLoopbackValidCount ++ ;
3071 	}
3072 
3073 	if ( up->iLoopbackValidCount < 2 ) {
3074 		return -1 ;
3075 	}
3076 
3077 	averTime.tv_usec = 0;
3078 
3079 	for ( i = 0 ; i < MAX_LOOPBACK && i < up->iLoopbackCount ; i ++ ) {
3080 		if ( up->bLoopbackTimeout[i]
3081 		  || up->delayTime[i].tv_sec  > iThresholdSecond
3082 		|| ( up->delayTime[i].tv_sec == iThresholdSecond
3083 		  && up->delayTime[i].tv_usec > iThresholdMicroSecond ) ) {
3084 			continue ;
3085 		}
3086 		if ( up->iLoopbackValidCount >= 3 && i == maxIndex ) {
3087 			continue ;
3088 		}
3089 		if ( up->iLoopbackValidCount >= 4 && i == minIndex ) {
3090 			continue ;
3091 		}
3092 		averTime.tv_usec += up->delayTime[i].tv_usec ;
3093 		iAverCount ++ ;
3094 	}
3095 
3096 	if ( iAverCount == 0 ) {
3097 		/* This is never happened. */
3098 		/* Previous for-if-for blocks assure iAverCount > 0. */
3099 		/* This code avoids a claim by the coverity scan tool. */
3100 		return -1 ;
3101 	}
3102 
3103 	/* mode 101 = 1%, mode 150 = 50%, mode 180 = 80% */
3104 
3105 	iPercent = ( peer->ttl - 100 ) ;
3106 
3107 	/* Average delay time in milli second */
3108 
3109 	return ( ( averTime.tv_usec / iAverCount ) * iPercent ) / 100000 ;
3110 
3111 }
3112 
3113 /******************************/
3114 static int
3115 teljjy_idle_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3116 {
3117 
3118 	DEBUG_TELJJY_PRINTF( "teljjy_idle_ignore" ) ;
3119 
3120 	return TELJJY_STAY_CLOCK_STATE ;
3121 
3122 }
3123 
3124 /******************************/
3125 static int
3126 teljjy_idle_dialout ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3127 {
3128 
3129 	DEBUG_TELJJY_PRINTF( "teljjy_idle_dialout" ) ;
3130 
3131 	modem_connect ( peer->refclkunit, peer ) ;
3132 
3133 	return TELJJY_CHANGE_CLOCK_STATE ;
3134 
3135 }
3136 
3137 /******************************/
3138 static int
3139 teljjy_dial_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3140 {
3141 
3142 	DEBUG_TELJJY_PRINTF( "teljjy_dial_ignore" ) ;
3143 
3144 	return TELJJY_STAY_CLOCK_STATE ;
3145 
3146 }
3147 
3148 /******************************/
3149 static int
3150 teljjy_dial_login ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3151 {
3152 
3153 	DEBUG_TELJJY_PRINTF( "teljjy_dial_login" ) ;
3154 
3155 	return TELJJY_CHANGE_CLOCK_STATE ;
3156 
3157 }
3158 
3159 /******************************/
3160 static int
3161 teljjy_dial_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3162 {
3163 
3164 	DEBUG_TELJJY_PRINTF( "teljjy_dial_disc" ) ;
3165 
3166 	return TELJJY_CHANGE_CLOCK_STATE ;
3167 
3168 }
3169 
3170 /******************************/
3171 static int
3172 teljjy_login_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3173 {
3174 
3175 	DEBUG_TELJJY_PRINTF( "teljjy_login_ignore" ) ;
3176 
3177 	return TELJJY_STAY_CLOCK_STATE ;
3178 
3179 }
3180 
3181 /******************************/
3182 static int
3183 teljjy_login_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3184 {
3185 
3186 	DEBUG_TELJJY_PRINTF( "teljjy_login_disc" ) ;
3187 
3188 	return TELJJY_CHANGE_CLOCK_STATE ;
3189 
3190 }
3191 
3192 /******************************/
3193 static int
3194 teljjy_login_conn ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3195 {
3196 
3197 	int	i ;
3198 
3199 	DEBUG_TELJJY_PRINTF( "teljjy_login_conn" ) ;
3200 
3201 	up->bLineError = FALSE ;
3202 	up->iClockCommandSeq = 0 ;
3203 	up->iTimestampCount = 0 ;
3204 	up->iLoopbackCount = 0 ;
3205 	for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) {
3206 		up->bLoopbackTimeout[i] = FALSE ;
3207 	}
3208 
3209 	return TELJJY_CHANGE_CLOCK_STATE ;
3210 
3211 }
3212 
3213 /******************************/
3214 static int
3215 teljjy_login_login ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3216 {
3217 
3218 	const char *	pCmd ;
3219 	int		iCmdLen ;
3220 
3221 	DEBUG_TELJJY_PRINTF( "teljjy_login_login" ) ;
3222 
3223 	/* Send a guest user ID */
3224 	pCmd = "TJJY\r" ;
3225 
3226 	/* Send login ID */
3227 	iCmdLen = strlen( pCmd ) ;
3228 	if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
3229 		refclock_report( peer, CEVNT_FAULT ) ;
3230 	}
3231 
3232 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
3233 
3234 	return TELJJY_STAY_CLOCK_STATE ;
3235 
3236 }
3237 
3238 /******************************/
3239 static int
3240 teljjy_login_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3241 {
3242 
3243 	DEBUG_TELJJY_PRINTF( "teljjy_login_silent" ) ;
3244 
3245 	if ( write( pp->io.fd, "\r", 1 ) != 1 ) {
3246 		refclock_report( peer, CEVNT_FAULT ) ;
3247 	}
3248 
3249 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, "\r" ) ;
3250 
3251 	up->iTeljjySilentTimer = 0 ;
3252 
3253 	return TELJJY_CHANGE_CLOCK_STATE ;
3254 
3255 }
3256 
3257 /******************************/
3258 static int
3259 teljjy_login_error ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3260 {
3261 
3262 	DEBUG_TELJJY_PRINTF( "teljjy_login_error" ) ;
3263 
3264 	return TELJJY_CHANGE_CLOCK_STATE ;
3265 
3266 }
3267 
3268 /******************************/
3269 static int
3270 teljjy_conn_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3271 {
3272 
3273 	DEBUG_TELJJY_PRINTF( "teljjy_conn_ignore" ) ;
3274 
3275 	return TELJJY_STAY_CLOCK_STATE ;
3276 
3277 }
3278 
3279 /******************************/
3280 static int
3281 teljjy_conn_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3282 {
3283 
3284 	DEBUG_TELJJY_PRINTF( "teljjy_conn_disc" ) ;
3285 
3286 	return TELJJY_CHANGE_CLOCK_STATE ;
3287 
3288 }
3289 
3290 /******************************/
3291 static int
3292 teljjy_conn_send ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3293 {
3294 
3295 	const char *	pCmd ;
3296 	int		i, iLen, iNextClockState ;
3297 
3298 	DEBUG_TELJJY_PRINTF( "teljjy_conn_send" ) ;
3299 
3300 	if ( up->iClockCommandSeq > 0
3301 	  && teljjy_command_sequence[up->iClockCommandSeq].command == NULL ) {
3302 		/* Command sequence has been completed */
3303 	  	return TELJJY_CHANGE_CLOCK_STATE ;
3304 	}
3305 
3306 	if ( up->iClockCommandSeq == 0 && peer->ttl == 100 ) {
3307 		/* Skip loopback */
3308 
3309 		up->iClockCommandSeq = TELJJY_COMMAND_START_SKIP_LOOPBACK ;
3310 
3311 	} else if ( up->iClockCommandSeq == 0 && peer->ttl != 100 ) {
3312 		/* Loopback start */
3313 
3314 		up->iLoopbackCount = 0 ;
3315 		for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) {
3316 			up->bLoopbackTimeout[i] = FALSE ;
3317 		}
3318 
3319 	} else if ( up->iClockCommandSeq > 0 && peer->ttl != 100
3320 		 && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK
3321 		 && up->iLoopbackCount < MAX_LOOPBACK ) {
3322 		/* Loopback character comes */
3323 #ifdef DEBUG
3324 		if ( debug ) {
3325 			printf( "refclock_jjy.c : teljjy_conn_send : iLoopbackCount=%d\n",
3326 				 up->iLoopbackCount ) ;
3327 		}
3328 #endif
3329 
3330 		teljjy_setDelay( peer, up ) ;
3331 
3332 		up->iLoopbackCount ++ ;
3333 
3334 	}
3335 
3336 	up->iClockCommandSeq++ ;
3337 
3338 	pCmd = teljjy_command_sequence[up->iClockCommandSeq].command ;
3339 	iLen = teljjy_command_sequence[up->iClockCommandSeq].commandLength ;
3340 
3341 	if ( pCmd != NULL ) {
3342 
3343 		if ( write( pp->io.fd, pCmd, iLen ) != iLen ) {
3344 			refclock_report( peer, CEVNT_FAULT ) ;
3345 		}
3346 
3347 		if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) {
3348 			/* Loopback character and timestamp */
3349 			gettimeofday( &(up->sendTime[up->iLoopbackCount]), NULL ) ;
3350 			up->bLoopbackMode = TRUE ;
3351 		} else {
3352 			/* Regular command */
3353 			up->bLoopbackMode = FALSE ;
3354 		}
3355 
3356 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
3357 
3358 		if ( teljjy_command_sequence[up->iClockCommandSeq+1].command == NULL ) {
3359 			/* Last command of the command sequence */
3360 			iNextClockState = TELJJY_CHANGE_CLOCK_STATE ;
3361 		} else {
3362 			/* More commands to be issued */
3363 			iNextClockState = TELJJY_STAY_CLOCK_STATE ;
3364 		}
3365 
3366 	} else {
3367 
3368 		iNextClockState = TELJJY_CHANGE_CLOCK_STATE ;
3369 
3370 	}
3371 
3372 	return iNextClockState ;
3373 
3374 }
3375 
3376 /******************************/
3377 static int
3378 teljjy_conn_data ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3379 {
3380 
3381 	char	*pBuf ;
3382 	int	iLen, rc ;
3383 	char	sLog [ 80 ] ;
3384 	char	bAdjustment ;
3385 
3386 
3387 	DEBUG_TELJJY_PRINTF( "teljjy_conn_data" ) ;
3388 
3389 	if ( up->linediscipline == LDISC_RAW ) {
3390 		pBuf = up->sTextBuf ;
3391 		iLen = up->iTextBufLen ;
3392 	} else {
3393 		pBuf = pp->a_lastcode ;
3394 		iLen = pp->lencode ;
3395 	}
3396 
3397 	if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength == iLen
3398 	  && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK
3399 	  && up->sTextBuf[0] == *(teljjy_command_sequence[up->iClockCommandSeq].command)
3400 	  && up->iLoopbackCount < MAX_LOOPBACK ) {
3401 		/* Loopback */
3402 
3403 		teljjy_setDelay( peer, up ) ;
3404 
3405 		up->iLoopbackCount ++ ;
3406 
3407 	} else if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength == iLen
3408 	    && strncmp( pBuf, teljjy_command_sequence[up->iClockCommandSeq].command, iLen ) == 0 ) {
3409 		/* Maybe echoback */
3410 
3411 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, JJY_CLOCKSTATS_MESSAGE_ECHOBACK ) ;
3412 
3413 	} else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen
3414 		 && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_4DATE ) {
3415 		/* 4DATE<CR> -> YYYYMMDD<CR> */
3416 
3417 		rc = sscanf ( pBuf, "%4d%2d%2d", &up->year, &up->month, &up->day ) ;
3418 
3419 		if ( rc != 3 || up->year < 2000 || 2099 <= up->year
3420 		  || up->month < 1 || 12 < up->month || up->day < 1 || 31 < up->day ) {
3421 			/* Invalid date */
3422 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE,
3423 				  rc, up->year, up->month, up->day ) ;
3424 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
3425 			up->bLineError = TRUE ;
3426 		}
3427 
3428 	} else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen
3429 		 && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LEAPSEC
3430 	         && ( strncmp( pBuf, " 0", 2 ) == 0 || strncmp( pBuf, "+1", 2 ) == 0 || strncmp( pBuf, "-1", 2 ) == 0 ) ) {
3431 		/* LEAPSEC<CR> -> XX<CR> ( One of <SP>0, +1, -1 ) */
3432 
3433 		rc = sscanf ( pBuf, "%2d", &up->leapsecond ) ;
3434 
3435 		if ( rc != 1 || up->leapsecond < -1 || 1 < up->leapsecond ) {
3436 			/* Invalid leap second */
3437 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_LEAP,
3438 				  pBuf ) ;
3439 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
3440 			up->bLineError = TRUE ;
3441 		}
3442 
3443 	} else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen
3444 		 && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_TIME ) {
3445 		/* TIME<CR> -> HHMMSS<CR> ( 3 times on second ) */
3446 
3447 		rc = sscanf ( pBuf, "%2d%2d%2d", &up->hour, &up->minute, &up->second ) ;
3448 
3449 		if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
3450 			/* Invalid time */
3451 			snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
3452 				  rc, up->hour, up->minute, up->second ) ;
3453 			jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
3454 			up->bLineError = TRUE ;
3455 		}
3456 		up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ;
3457 
3458 		up->iTimestampCount++ ;
3459 
3460 		if ( up->iTimestampCount == 6 && ! up->bLineError ) {
3461 #if DEBUG
3462 			printf( "refclock_jjy.c : teljjy_conn_data : bLineError=%d iTimestamp=%d, %d, %d\n",
3463 				up->bLineError,
3464 				up->iTimestamp[3], up->iTimestamp[4], up->iTimestamp[5] ) ;
3465 #endif
3466 			bAdjustment = TRUE ;
3467 
3468 			if ( peer->ttl == 100 ) {
3469 				/* mode=100 */
3470 				up->msecond = 0 ;
3471 			} else {
3472 				/* mode=101 to 110 */
3473 				up->msecond = teljjy_getDelay( peer, up ) ;
3474 				if (up->msecond < 0 ) {
3475 					up->msecond = 0 ;
3476 					bAdjustment = FALSE ;
3477 				}
3478 			}
3479 
3480 			if ( ( up->iTimestamp[3] - 15 ) <= up->iTimestamp[2]
3481 			  &&   up->iTimestamp[2]        <= up->iTimestamp[3]
3482 			  && ( up->iTimestamp[3] +  1 ) == up->iTimestamp[4]
3483 			  && ( up->iTimestamp[4] +  1 ) == up->iTimestamp[5] ) {
3484 				/* Non over midnight */
3485 
3486 				jjy_synctime( peer, pp, up ) ;
3487 
3488 				if ( peer->ttl != 100 ) {
3489 					if ( bAdjustment ) {
3490 						snprintf( sLog, sizeof(sLog),
3491 							  JJY_CLOCKSTATS_MESSAGE_DELAY_ADJUST,
3492 							  up->msecond, up->iLoopbackValidCount, MAX_LOOPBACK ) ;
3493 						jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
3494 					} else {
3495 						snprintf( sLog, sizeof(sLog),
3496 							  JJY_CLOCKSTATS_MESSAGE_DELAY_UNADJUST,
3497 							   up->iLoopbackValidCount, MAX_LOOPBACK ) ;
3498 						jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
3499 					}
3500 				}
3501 
3502 			}
3503 		}
3504 
3505 	} else if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength != iLen
3506 		 && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) {
3507 		/* Loopback noise ( Unexpected replay ) */
3508 
3509 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_IGNORE_REPLY,
3510 			  pBuf ) ;
3511 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ;
3512 
3513 	} else {
3514 
3515 		up->bLineError = TRUE ;
3516 
3517 		snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
3518 			  pBuf ) ;
3519 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
3520 
3521 	}
3522 
3523 	return TELJJY_STAY_CLOCK_STATE ;
3524 
3525 }
3526 
3527 /******************************/
3528 static int
3529 teljjy_conn_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3530 {
3531 
3532 	const char *	pCmd ;
3533 
3534 	DEBUG_TELJJY_PRINTF( "teljjy_conn_silent" ) ;
3535 
3536 	if ( up->iClockCommandSeq >= 1
3537 	  && up->iClockCommandSeq < TELJJY_COMMAND_START_SKIP_LOOPBACK ) {
3538 		/* Loopback */
3539 #ifdef DEBUG
3540 		if ( debug ) {
3541 			printf( "refclock_jjy.c : teljjy_conn_silent : call teljjy_conn_send\n" ) ;
3542 		}
3543 #endif
3544 		if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) {
3545 			up->bLoopbackTimeout[up->iLoopbackCount] = TRUE ;
3546 		}
3547 		up->iTeljjySilentTimer = 0 ;
3548 		return teljjy_conn_send( peer, pp, up ) ;
3549 	} else {
3550 		pCmd = "\r" ;
3551 	}
3552 
3553 	if ( write( pp->io.fd, pCmd, 1 ) != 1 ) {
3554 		refclock_report( peer, CEVNT_FAULT ) ;
3555 	}
3556 
3557 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
3558 
3559 	up->iTeljjySilentTimer = 0 ;
3560 
3561 	return TELJJY_STAY_CLOCK_STATE ;
3562 
3563 }
3564 
3565 /******************************/
3566 static int
3567 teljjy_conn_error ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3568 {
3569 
3570 	DEBUG_TELJJY_PRINTF( "teljjy_conn_error" ) ;
3571 
3572 	return TELJJY_CHANGE_CLOCK_STATE ;
3573 
3574 }
3575 
3576 /******************************/
3577 static int
3578 teljjy_bye_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3579 {
3580 
3581 	DEBUG_TELJJY_PRINTF( "teljjy_bye_ignore" ) ;
3582 
3583 	return TELJJY_STAY_CLOCK_STATE ;
3584 
3585 }
3586 
3587 /******************************/
3588 static int
3589 teljjy_bye_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3590 {
3591 
3592 	DEBUG_TELJJY_PRINTF( "teljjy_bye_disc" ) ;
3593 
3594 	return TELJJY_CHANGE_CLOCK_STATE ;
3595 
3596 }
3597 
3598 /******************************/
3599 static int
3600 teljjy_bye_modem ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3601 {
3602 
3603 	DEBUG_TELJJY_PRINTF( "teljjy_bye_modem" ) ;
3604 
3605 	modem_disconnect ( peer->refclkunit, peer ) ;
3606 
3607 	return TELJJY_STAY_CLOCK_STATE ;
3608 
3609 }
3610 
3611 /*################################################################################################*/
3612 /*################################################################################################*/
3613 /*##												##*/
3614 /*##    Modem control finite state machine							##*/
3615 /*##												##*/
3616 /*################################################################################################*/
3617 /*################################################################################################*/
3618 
3619 /* struct jjyunit.iModemState */
3620 
3621 #define	MODEM_STATE_DISCONNECT		0
3622 #define	MODEM_STATE_INITIALIZE		1
3623 #define	MODEM_STATE_DAILING		2
3624 #define	MODEM_STATE_CONNECT		3
3625 #define	MODEM_STATE_ESCAPE		4
3626 
3627 /* struct jjyunit.iModemEvent */
3628 
3629 #define MODEM_EVENT_NULL		0
3630 #define	MODEM_EVENT_INITIALIZE		1
3631 #define	MODEM_EVENT_DIALOUT		2
3632 #define	MODEM_EVENT_DISCONNECT		3
3633 #define	MODEM_EVENT_RESP_OK		4
3634 #define	MODEM_EVENT_RESP_CONNECT	5
3635 #define	MODEM_EVENT_RESP_RING		6
3636 #define	MODEM_EVENT_RESP_NO_CARRIER	7
3637 #define	MODEM_EVENT_RESP_ERROR		8
3638 #define	MODEM_EVENT_RESP_CONNECT_X	9
3639 #define	MODEM_EVENT_RESP_NO_DAILTONE	10
3640 #define	MODEM_EVENT_RESP_BUSY		11
3641 #define	MODEM_EVENT_RESP_NO_ANSWER	12
3642 #define	MODEM_EVENT_RESP_UNKNOWN	13
3643 #define	MODEM_EVENT_SILENT		14
3644 #define	MODEM_EVENT_TIMEOUT		15
3645 
3646 /* Function prototypes */
3647 
3648 static	void	modem_control		( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3649 
3650 static	int 	modem_disc_ignore	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3651 static	int 	modem_disc_init  	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3652 static	int 	modem_init_ignore	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3653 static	int 	modem_init_start 	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3654 static	int 	modem_init_disc  	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3655 static	int 	modem_init_resp00	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3656 static	int 	modem_init_resp04	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3657 static	int 	modem_dial_ignore	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3658 static	int 	modem_dial_dialout	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3659 static	int 	modem_dial_escape	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3660 static	int 	modem_dial_connect	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3661 static	int 	modem_dial_disc  	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3662 static	int 	modem_conn_ignore	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3663 static	int 	modem_conn_escape	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3664 static	int 	modem_esc_ignore	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3665 static	int 	modem_esc_escape	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3666 static	int 	modem_esc_data  	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3667 static	int 	modem_esc_silent	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3668 static	int 	modem_esc_disc  	( struct peer *, struct refclockproc *, struct jjyunit * ) ;
3669 
3670 static int ( *pModemHandler [ ] [ 5 ] ) ( struct peer *, struct refclockproc *, struct jjyunit * ) =
3671 {                         	/*STATE_DISCONNECT   STATE_INITIALIZE   STATE_DAILING       STATE_CONNECT      STATE_ESCAPE     */
3672 /* NULL                 */	{ modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_ignore },
3673 /* INITIALIZE           */	{ modem_disc_init  , modem_init_start , modem_dial_ignore , modem_conn_ignore, modem_esc_ignore },
3674 /* DIALOUT              */	{ modem_disc_ignore, modem_init_ignore, modem_dial_dialout, modem_conn_ignore, modem_esc_ignore },
3675 /* DISCONNECT           */	{ modem_disc_ignore, modem_init_disc  , modem_dial_escape , modem_conn_escape, modem_esc_escape },
3676 /* RESP: 0: OK          */	{ modem_disc_ignore, modem_init_resp00, modem_dial_ignore , modem_conn_ignore, modem_esc_data   },
3677 /* RESP: 1: CONNECT     */	{ modem_disc_ignore, modem_init_ignore, modem_dial_connect, modem_conn_ignore, modem_esc_data   },
3678 /* RESP: 2: RING        */	{ modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_data   },
3679 /* RESP: 3: NO CARRIER  */	{ modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
3680 /* RESP: 4: ERROR       */	{ modem_disc_ignore, modem_init_resp04, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
3681 /* RESP: 5: CONNECT     */	{ modem_disc_ignore, modem_init_ignore, modem_dial_connect, modem_conn_ignore, modem_esc_data   },
3682 /* RESP: 6: NO DAILTONE */	{ modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
3683 /* RESP: 7: BUSY        */	{ modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
3684 /* RESP: 8: NO ANSWER   */	{ modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
3685 /* RESP: 9: UNKNOWN     */	{ modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_data   },
3686 /* SILENT               */	{ modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_silent },
3687 /* TIMEOUT              */	{ modem_disc_ignore, modem_init_disc  , modem_dial_escape , modem_conn_escape, modem_esc_disc   }
3688 } ;
3689 
3690 static short iModemNextState [ ] [ 5 ] =
3691 {                         	/*STATE_DISCONNECT        STATE_INITIALIZE        STATE_DAILING        STATE_CONNECT        STATE_ESCAPE           */
3692 /* NULL                 */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3693 /* INITIALIZE           */	{ MODEM_STATE_INITIALIZE, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3694 /* DIALOUT              */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3695 /* DISCONNECT           */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_DISCONNECT, MODEM_STATE_ESCAPE    , MODEM_STATE_ESCAPE , MODEM_STATE_ESCAPE     },
3696 /* RESP: 0: OK          */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_DAILING   , MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3697 /* RESP: 1: CONNECT     */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_CONNECT   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3698 /* RESP: 2: RING        */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3699 /* RESP: 3: NO CARRIER  */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3700 /* RESP: 4: ERROR       */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_DAILING   , MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3701 /* RESP: 5: CONNECT X   */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_CONNECT   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3702 /* RESP: 6: NO DAILTONE */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3703 /* RESP: 7: BUSY        */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3704 /* RESP: 8: NO ANSWER   */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3705 /* RESP: 9: UNKNOWN     */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
3706 /* SILENT               */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_DISCONNECT },
3707 /* TIMEOUT              */	{ MODEM_STATE_DISCONNECT, MODEM_STATE_DISCONNECT, MODEM_STATE_ESCAPE    , MODEM_STATE_ESCAPE , MODEM_STATE_DISCONNECT }
3708 } ;
3709 
3710 static short iModemPostEvent [ ] [ 5 ] =
3711 {                         	/*STATE_DISCONNECT        STATE_INITIALIZE     STATE_DAILING           STATE_CONNECT           STATE_ESCAPE     */
3712 /* NULL                 */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3713 /* INITIALIZE           */	{ MODEM_EVENT_INITIALIZE, MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3714 /* DIALOUT              */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3715 /* DISCONNECT           */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_DISCONNECT, MODEM_EVENT_DISCONNECT, MODEM_EVENT_NULL },
3716 /* RESP: 0: OK          */	{ MODEM_EVENT_NULL      , MODEM_EVENT_DIALOUT, MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3717 /* RESP: 1: CONNECT     */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3718 /* RESP: 2: RING        */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3719 /* RESP: 3: NO CARRIER  */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3720 /* RESP: 4: ERROR       */	{ MODEM_EVENT_NULL      , MODEM_EVENT_DIALOUT, MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3721 /* RESP: 5: CONNECT X   */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3722 /* RESP: 6: NO DAILTONE */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3723 /* RESP: 7: BUSY        */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3724 /* RESP: 8: NO ANSWER   */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3725 /* RESP: 9: UNKNOWN     */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3726 /* SILENT               */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
3727 /* TIMEOUT              */	{ MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_DISCONNECT, MODEM_EVENT_DISCONNECT, MODEM_EVENT_NULL }
3728 } ;
3729 
3730 static short iModemSilentTimeout [ 5 ] = { 0,  0,  0, 0,  5 } ;
3731 static short iModemStateTimeout  [ 5 ] = { 0, 20, 90, 0, 20 } ;
3732 
3733 #define	STAY_MODEM_STATE	0
3734 #define	CHANGE_MODEM_STATE	1
3735 
3736 #ifdef	DEBUG
3737 #define	DEBUG_MODEM_PRINTF(sFunc)	{ if ( debug ) { printf ( "refclock_jjy.c : %s : iModemState=%d iModemEvent=%d iModemSilentTimer=%d iModemStateTimer=%d\n", sFunc, up->iModemState, up->iModemEvent, up->iModemSilentTimer, up->iModemStateTimer ) ; } }
3738 #else
3739 #define	DEBUG_MODEM_PRINTF(sFunc)
3740 #endif
3741 
3742 /**************************************************************************************************/
3743 
3744 static short
3745 getModemState ( struct jjyunit *up )
3746 {
3747 	return up->iModemState ;
3748 }
3749 
3750 /**************************************************************************************************/
3751 
3752 static int
3753 isModemStateConnect ( short iCheckState )
3754 {
3755 	return ( iCheckState == MODEM_STATE_CONNECT ) ;
3756 }
3757 
3758 /**************************************************************************************************/
3759 
3760 static int
3761 isModemStateDisconnect ( short iCheckState )
3762 {
3763 	return ( iCheckState == MODEM_STATE_DISCONNECT ) ;
3764 }
3765 
3766 /**************************************************************************************************/
3767 
3768 static int
3769 isModemStateTimerOn ( struct jjyunit *up )
3770 {
3771 	return ( iModemSilentTimeout[up->iModemState] != 0 || iModemStateTimeout[up->iModemState] != 0 ) ;
3772 }
3773 
3774 /**************************************************************************************************/
3775 
3776 static void
3777 modem_connect ( int unit, struct peer *peer )
3778 {
3779 	struct	refclockproc	*pp;
3780 	struct	jjyunit 	*up;
3781 
3782 	pp = peer->procptr ;
3783 	up = pp->unitptr ;
3784 
3785 	DEBUG_MODEM_PRINTF( "modem_connect" ) ;
3786 
3787 	up->iModemEvent = MODEM_EVENT_INITIALIZE ;
3788 
3789 	modem_control ( peer, pp, up ) ;
3790 
3791 }
3792 
3793 /**************************************************************************************************/
3794 
3795 static void
3796 modem_disconnect ( int unit, struct peer *peer )
3797 {
3798 	struct	refclockproc	*pp;
3799 	struct	jjyunit 	*up;
3800 
3801 	pp = peer->procptr ;
3802 	up = pp->unitptr ;
3803 
3804 	DEBUG_MODEM_PRINTF( "modem_disconnect" ) ;
3805 
3806 	up->iModemEvent = MODEM_EVENT_DISCONNECT ;
3807 
3808 	modem_control ( peer, pp, up ) ;
3809 
3810 }
3811 
3812 /**************************************************************************************************/
3813 
3814 static int
3815 modem_receive ( struct recvbuf *rbufp )
3816 {
3817 
3818 	struct	peer		*peer;
3819 	struct	jjyunit		*up;
3820 	struct	refclockproc	*pp;
3821 	char	*pBuf ;
3822 	int	iLen ;
3823 
3824 #ifdef DEBUG
3825 	static const char *sFunctionName = "modem_receive" ;
3826 #endif
3827 
3828 	peer = rbufp->recv_peer ;
3829 	pp = peer->procptr ;
3830 	up = pp->unitptr ;
3831 
3832 	DEBUG_MODEM_PRINTF( sFunctionName ) ;
3833 
3834 	if ( up->linediscipline == LDISC_RAW ) {
3835 		pBuf = up->sTextBuf ;
3836 		iLen = up->iTextBufLen ;
3837 	} else {
3838 		pBuf = pp->a_lastcode ;
3839 		iLen = pp->lencode ;
3840 	}
3841 
3842 	if      ( iLen ==  2 && strncmp( pBuf, "OK"         ,  2 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_OK          ; }
3843 	else if ( iLen ==  7 && strncmp( pBuf, "CONNECT"    ,  7 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_CONNECT     ; }
3844 	else if ( iLen ==  4 && strncmp( pBuf, "RING"       ,  4 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_RING        ; }
3845 	else if ( iLen == 10 && strncmp( pBuf, "NO CARRIER" , 10 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_CARRIER  ; }
3846 	else if ( iLen ==  5 && strncmp( pBuf, "ERROR"      ,  5 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_ERROR       ; }
3847 	else if ( iLen >=  8 && strncmp( pBuf, "CONNECT "   ,  8 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_CONNECT_X   ; }
3848 	else if ( iLen == 11 && strncmp( pBuf, "NO DAILTONE", 11 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_DAILTONE ; }
3849 	else if ( iLen ==  4 && strncmp( pBuf, "BUSY"       ,  4 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_BUSY        ; }
3850 	else if ( iLen ==  9 && strncmp( pBuf, "NO ANSWER"  ,  9 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_ANSWER   ; }
3851 	else                                                              { up->iModemEvent = MODEM_EVENT_RESP_UNKNOWN     ; }
3852 
3853 #ifdef DEBUG
3854 	if ( debug ) {
3855 		char	sResp [ 40 ] ;
3856 		int	iCopyLen ;
3857 		iCopyLen = ( iLen <= sizeof(sResp)-1 ? iLen : sizeof(sResp)-1 ) ;
3858 		strncpy( sResp, pBuf, iLen <= sizeof(sResp)-1 ? iLen : sizeof(sResp)-1 ) ;
3859 		sResp[iCopyLen] = 0 ;
3860 		printf ( "refclock_jjy.c : modem_receive : iLen=%d pBuf=[%s] iModemEvent=%d\n", iCopyLen, sResp, up->iModemEvent ) ;
3861 	}
3862 #endif
3863 	modem_control ( peer, pp, up ) ;
3864 
3865 	return 0 ;
3866 
3867 }
3868 
3869 /**************************************************************************************************/
3870 
3871 static void
3872 modem_timer ( int unit, struct peer *peer )
3873 {
3874 
3875 	struct	refclockproc *pp ;
3876 	struct	jjyunit      *up ;
3877 
3878 	pp = peer->procptr ;
3879 	up = pp->unitptr ;
3880 
3881 	DEBUG_MODEM_PRINTF( "modem_timer" ) ;
3882 
3883 	if ( iModemSilentTimeout[up->iModemState] != 0 ) {
3884 		up->iModemSilentTimer++ ;
3885 		if ( iModemSilentTimeout[up->iModemState] <= up->iModemSilentTimer ) {
3886 			up->iModemEvent = MODEM_EVENT_SILENT ;
3887 			modem_control ( peer, pp, up ) ;
3888 		}
3889 	}
3890 
3891 	if ( iModemStateTimeout[up->iModemState] != 0 ) {
3892 		up->iModemStateTimer++ ;
3893 		if ( iModemStateTimeout[up->iModemState] <= up->iModemStateTimer ) {
3894 			up->iModemEvent = MODEM_EVENT_TIMEOUT ;
3895 			modem_control ( peer, pp, up ) ;
3896 		}
3897 	}
3898 
3899 }
3900 
3901 /**************************************************************************************************/
3902 
3903 static void
3904 modem_control ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3905 {
3906 
3907 	int	rc ;
3908 	short	iPostEvent = MODEM_EVENT_NULL ;
3909 
3910 	DEBUG_MODEM_PRINTF( "modem_control" ) ;
3911 
3912 	rc = (*pModemHandler[up->iModemEvent][up->iModemState])( peer, pp, up ) ;
3913 
3914 	if ( rc == CHANGE_MODEM_STATE ) {
3915 		iPostEvent = iModemPostEvent[up->iModemEvent][up->iModemState] ;
3916 #ifdef DEBUG
3917 		if ( debug ) {
3918 			printf( "refclock_jjy.c : modem_control : iModemState=%d -> %d  iPostEvent=%d\n",
3919 				 up->iModemState, iModemNextState[up->iModemEvent][up->iModemState], iPostEvent ) ;
3920 		}
3921 #endif
3922 
3923 		if ( up->iModemState != iModemNextState[up->iModemEvent][up->iModemState] ) {
3924 			up->iModemSilentCount = 0 ;
3925 			up->iModemStateTimer = 0 ;
3926 			up->iModemCommandSeq = 0 ;
3927 		}
3928 
3929 		up->iModemState = iModemNextState[up->iModemEvent][up->iModemState] ;
3930 	}
3931 
3932 	if ( iPostEvent != MODEM_EVENT_NULL ) {
3933 		up->iModemEvent = iPostEvent ;
3934 		modem_control ( peer, pp, up ) ;
3935 	}
3936 
3937 	up->iModemEvent = MODEM_EVENT_NULL ;
3938 
3939 }
3940 
3941 /******************************/
3942 static int
3943 modem_disc_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3944 {
3945 
3946 	DEBUG_MODEM_PRINTF( "modem_disc_ignore" ) ;
3947 
3948 	return STAY_MODEM_STATE ;
3949 
3950 }
3951 
3952 /******************************/
3953 static int
3954 modem_disc_init ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3955 {
3956 
3957 	DEBUG_MODEM_PRINTF( "modem_disc_init" ) ;
3958 
3959 	return CHANGE_MODEM_STATE ;
3960 
3961 }
3962 
3963 /******************************/
3964 static int
3965 modem_init_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3966 {
3967 
3968 	DEBUG_MODEM_PRINTF( "modem_init_ignore" ) ;
3969 
3970 	return STAY_MODEM_STATE ;
3971 
3972 }
3973 
3974 /******************************/
3975 static int
3976 modem_init_start ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3977 {
3978 
3979 	DEBUG_MODEM_PRINTF( "modem_init_start" ) ;
3980 
3981 	up->iModemCommandSeq = 0 ;
3982 
3983 #ifdef DEBUG
3984 	if ( debug ) {
3985 		printf( "refclock_jjy.c : modem_init_start : call modem_init_resp00\n" ) ;
3986 	}
3987 #endif
3988 
3989 	return modem_init_resp00( peer, pp, up ) ;
3990 
3991 }
3992 
3993 /******************************/
3994 static int
3995 modem_init_resp00 ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
3996 {
3997 
3998 	const char *	pCmd ;
3999 	char		cBuf [ 46 ] ;
4000 	int		iCmdLen ;
4001 	int		iErrorCorrection, iSpeakerSwitch, iSpeakerVolume ;
4002 	int		iNextModemState = STAY_MODEM_STATE ;
4003 
4004 	DEBUG_MODEM_PRINTF( "modem_init_resp00" ) ;
4005 
4006 	up->iModemCommandSeq++ ;
4007 
4008 	switch ( up->iModemCommandSeq ) {
4009 
4010 	case 1 :
4011 		/* En = Echoback      0:Off      1:On   */
4012 		/* Qn = Result codes  0:On       1:Off  */
4013 		/* Vn = Result codes  0:Numeric  1:Text */
4014 		pCmd = "ATE0Q0V1\r\n" ;
4015 		break ;
4016 
4017 	case 2 :
4018 		/* Mn = Speaker switch  0:Off  1:On until remote carrier detected  2:On */
4019 		if ( ( pp->sloppyclockflag & CLK_FLAG3 ) == 0 ) {
4020 			/* fudge 127.127.40.n flag3 0 */
4021 			iSpeakerSwitch = 0 ;
4022 		} else {
4023 			/* fudge 127.127.40.n flag3 1 */
4024 			iSpeakerSwitch = 2 ;
4025 		}
4026 
4027 		/* Ln = Speaker volume  0:Very low  1:Low  2:Middle  3:High */
4028 		if ( ( pp->sloppyclockflag & CLK_FLAG4 ) == 0 ) {
4029 			/* fudge 127.127.40.n flag4 0 */
4030 			iSpeakerVolume = 1 ;
4031 		} else {
4032 			/* fudge 127.127.40.n flag4 1 */
4033 			iSpeakerVolume = 2 ;
4034 		}
4035 
4036 		pCmd = cBuf ;
4037 		snprintf( cBuf, sizeof(cBuf), "ATM%dL%d\r\n", iSpeakerSwitch, iSpeakerVolume ) ;
4038 		break ;
4039 
4040 	case 3 :
4041 		/* &Kn = Flow control  4:XON/XOFF */
4042 		pCmd = "AT&K4\r\n" ;
4043 		break ;
4044 
4045 	case 4 :
4046 		/* +MS = Protocol  V22B:1200,2400bps�iV.22bis) */
4047 		pCmd = "AT+MS=V22B\r\n" ;
4048 		break ;
4049 
4050 	case 5 :
4051 		/* %Cn = Data compression  0:No data compression */
4052 		pCmd = "AT%C0\r\n" ;
4053 		break ;
4054 
4055 	case 6 :
4056 		/* \Nn = Error correction  0:Normal mode  1:Direct mode  2:V42,MNP  3:V42,MNP,Normal */
4057 		if ( ( pp->sloppyclockflag & CLK_FLAG2 ) == 0 ) {
4058 			/* fudge 127.127.40.n flag2 0 */
4059 			iErrorCorrection = 0 ;
4060 		} else {
4061 			/* fudge 127.127.40.n flag2 1 */
4062 			iErrorCorrection = 3 ;
4063 		}
4064 
4065 		pCmd = cBuf ;
4066 		snprintf( cBuf, sizeof(cBuf), "AT\\N%d\r\n", iErrorCorrection ) ;
4067 		break ;
4068 
4069 	case 7 :
4070 		/* Hn = Hook  0:Hook-On ( Disconnect )  1:Hook-Off ( Connect ) */
4071 		pCmd = "ATH1\r\n" ;
4072 		break ;
4073 
4074 	case 8 :
4075 		/* Initialize completion */
4076 		pCmd = NULL ;
4077 		iNextModemState = CHANGE_MODEM_STATE ;
4078 		break ;
4079 
4080 	default :
4081 		pCmd = NULL ;
4082 		break ;
4083 
4084 	}
4085 
4086 	if ( pCmd != NULL ) {
4087 
4088 		iCmdLen = strlen( pCmd ) ;
4089 		if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
4090 			refclock_report( peer, CEVNT_FAULT ) ;
4091 		}
4092 
4093 		jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
4094 
4095 	}
4096 
4097 	return iNextModemState ;
4098 
4099 }
4100 
4101 /******************************/
4102 static int
4103 modem_init_resp04 ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4104 {
4105 
4106 	DEBUG_MODEM_PRINTF( "modem_init_resp04" ) ;
4107 
4108 	return modem_init_resp00( peer, pp, up ) ;
4109 
4110 }
4111 
4112 /******************************/
4113 static int
4114 modem_init_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4115 {
4116 
4117 	DEBUG_MODEM_PRINTF( "modem_init_disc" ) ;
4118 #ifdef DEBUG
4119 	if ( debug ) {
4120 		printf( "refclock_jjy.c : modem_init_disc : call modem_esc_disc\n" ) ;
4121 	}
4122 #endif
4123 
4124 	return CHANGE_MODEM_STATE ;
4125 
4126 }
4127 
4128 /******************************/
4129 static int
4130 modem_dial_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4131 {
4132 
4133 	DEBUG_MODEM_PRINTF( "modem_dial_ignore" ) ;
4134 
4135 	return STAY_MODEM_STATE ;
4136 
4137 }
4138 
4139 /******************************/
4140 static int
4141 modem_dial_dialout ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4142 {
4143 
4144 	char	sCmd [ 46 ] ;
4145 	int	iCmdLen ;
4146 	char	cToneOrPulse ;
4147 
4148 	DEBUG_MODEM_PRINTF( "modem_dial_dialout" ) ;
4149 
4150 	/* Tone or Pulse */
4151 	if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
4152 		/* fudge 127.127.40.n flag1 0 */
4153 		cToneOrPulse = 'T' ;
4154 	} else {
4155 		/* fudge 127.127.40.n flag1 1 */
4156 		cToneOrPulse = 'P' ;
4157 	}
4158 
4159 	/* Connect ( Dial number ) */
4160 	snprintf( sCmd, sizeof(sCmd), "ATDW%c%s\r\n", cToneOrPulse, *sys_phone ) ;
4161 
4162 	/* Send command */
4163 	iCmdLen = strlen( sCmd ) ;
4164 	if ( write( pp->io.fd, sCmd, iCmdLen ) != iCmdLen ) {
4165 		refclock_report( peer, CEVNT_FAULT ) ;
4166 	}
4167 
4168 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, sCmd ) ;
4169 
4170 	return STAY_MODEM_STATE ;
4171 
4172 }
4173 
4174 /******************************/
4175 static int
4176 modem_dial_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4177 {
4178 
4179 	DEBUG_MODEM_PRINTF( "modem_dial_escape" ) ;
4180 #ifdef DEBUG
4181 	if ( debug ) {
4182 		printf( "refclock_jjy.c : modem_dial_escape : call modem_conn_escape\n" ) ;
4183 	}
4184 #endif
4185 
4186 	return modem_conn_escape( peer, pp, up ) ;
4187 
4188 }
4189 
4190 /******************************/
4191 static int
4192 modem_dial_connect ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4193 {
4194 
4195 	DEBUG_MODEM_PRINTF( "modem_dial_connect" ) ;
4196 
4197 	return CHANGE_MODEM_STATE ;
4198 
4199 }
4200 
4201 /******************************/
4202 static int
4203 modem_dial_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4204 {
4205 
4206 	DEBUG_MODEM_PRINTF( "modem_dial_disc" ) ;
4207 #ifdef DEBUG
4208 	if ( debug ) {
4209 		printf( "refclock_jjy.c : modem_dial_disc : call modem_esc_disc\n" ) ;
4210 	}
4211 #endif
4212 
4213 	modem_esc_disc( peer, pp, up ) ;
4214 
4215 	return CHANGE_MODEM_STATE ;
4216 
4217 }
4218 
4219 /******************************/
4220 static int
4221 modem_conn_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4222 {
4223 
4224 	DEBUG_MODEM_PRINTF( "modem_conn_ignore" ) ;
4225 
4226 	return STAY_MODEM_STATE ;
4227 
4228 }
4229 
4230 /******************************/
4231 static int
4232 modem_conn_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4233 {
4234 
4235 	DEBUG_MODEM_PRINTF( "modem_conn_escape" ) ;
4236 
4237 	return CHANGE_MODEM_STATE ;
4238 
4239 }
4240 
4241 /******************************/
4242 static int
4243 modem_esc_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4244 {
4245 
4246 	DEBUG_MODEM_PRINTF( "modem_esc_ignore" ) ;
4247 
4248 	return STAY_MODEM_STATE ;
4249 
4250 }
4251 
4252 /******************************/
4253 static int
4254 modem_esc_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4255 {
4256 
4257 	const char *	pCmd ;
4258 	int		iCmdLen ;
4259 
4260 	DEBUG_MODEM_PRINTF( "modem_esc_escape" ) ;
4261 
4262 	/* Escape command ( Go to command mode ) */
4263 	pCmd = "+++" ;
4264 
4265 	/* Send command */
4266 	iCmdLen = strlen( pCmd ) ;
4267 	if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
4268 		refclock_report( peer, CEVNT_FAULT ) ;
4269 	}
4270 
4271 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
4272 
4273 	return STAY_MODEM_STATE ;
4274 
4275 }
4276 
4277 /******************************/
4278 static int
4279 modem_esc_data ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4280 {
4281 
4282 	DEBUG_MODEM_PRINTF( "modem_esc_data" ) ;
4283 
4284 	up->iModemSilentTimer = 0 ;
4285 
4286 	return STAY_MODEM_STATE ;
4287 
4288 }
4289 
4290 /******************************/
4291 static int
4292 modem_esc_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4293 {
4294 
4295 	DEBUG_MODEM_PRINTF( "modem_esc_silent" ) ;
4296 
4297 	up->iModemSilentCount ++ ;
4298 
4299 	if ( up->iModemSilentCount < iModemStateTimeout[up->iModemState] / iModemSilentTimeout[up->iModemState] ) {
4300 #ifdef DEBUG
4301 		if ( debug ) {
4302 			printf( "refclock_jjy.c : modem_esc_silent : call modem_esc_escape\n" ) ;
4303 		}
4304 #endif
4305 		modem_esc_escape( peer, pp, up ) ;
4306 		up->iModemSilentTimer = 0 ;
4307 		return STAY_MODEM_STATE ;
4308 	}
4309 
4310 #ifdef DEBUG
4311 	if ( debug ) {
4312 		printf( "refclock_jjy.c : modem_esc_silent : call modem_esc_disc\n" ) ;
4313 	}
4314 #endif
4315 	return modem_esc_disc( peer, pp, up ) ;
4316 
4317 }
4318 /******************************/
4319 static int
4320 modem_esc_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
4321 {
4322 
4323 	const char *	pCmd ;
4324 	int		iCmdLen ;
4325 
4326 	DEBUG_MODEM_PRINTF( "modem_esc_disc" ) ;
4327 
4328 	/* Disconnect */
4329 	pCmd = "ATH0\r\n" ;
4330 
4331 	/* Send command */
4332 	iCmdLen = strlen( pCmd ) ;
4333 	if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
4334 		refclock_report( peer, CEVNT_FAULT ) ;
4335 	}
4336 
4337 	jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
4338 
4339 	return CHANGE_MODEM_STATE ;
4340 
4341 }
4342 
4343 /*################################################################################################*/
4344 /*################################################################################################*/
4345 /*##												##*/
4346 /*##    jjy_write_clockstats									##*/
4347 /*##												##*/
4348 /*################################################################################################*/
4349 /*################################################################################################*/
4350 
4351 static void
4352 jjy_write_clockstats ( struct peer *peer, int iMark, const char *pData )
4353 {
4354 
4355 	char		sLog [ 100 ] ;
4356 	const char *	pMark ;
4357 	int 		iMarkLen, iDataLen ;
4358 
4359 	switch ( iMark ) {
4360 	case JJY_CLOCKSTATS_MARK_JJY :
4361 		pMark = "JJY " ;
4362 		break ;
4363 	case JJY_CLOCKSTATS_MARK_SEND :
4364 		pMark = "--> " ;
4365 		break ;
4366 	case JJY_CLOCKSTATS_MARK_RECEIVE :
4367 		pMark = "<-- " ;
4368 		break ;
4369 	case JJY_CLOCKSTATS_MARK_INFORMATION :
4370 		pMark = "--- " ;
4371 		break ;
4372 	case JJY_CLOCKSTATS_MARK_ATTENTION :
4373 		pMark = "=== " ;
4374 		break ;
4375 	case JJY_CLOCKSTATS_MARK_WARNING :
4376 		pMark = "-W- " ;
4377 		break ;
4378 	case JJY_CLOCKSTATS_MARK_ERROR :
4379 		pMark = "-X- " ;
4380 		break ;
4381 	default :
4382 		pMark = "" ;
4383 		break ;
4384 	}
4385 
4386 	iDataLen = strlen( pData ) ;
4387 	iMarkLen = strlen( pMark ) ;
4388 	strcpy( sLog, pMark ) ; /* Harmless because of enough length */
4389 	printableString( sLog+iMarkLen, sizeof(sLog)-iMarkLen, pData, iDataLen ) ;
4390 
4391 #ifdef DEBUG
4392 	if ( debug ) {
4393 		printf( "refclock_jjy.c : clockstats : %s\n", sLog ) ;
4394 	}
4395 #endif
4396 	record_clock_stats( &peer->srcadr, sLog ) ;
4397 
4398 }
4399 
4400 /*################################################################################################*/
4401 /*################################################################################################*/
4402 /*##												##*/
4403 /*##    printableString										##*/
4404 /*##												##*/
4405 /*################################################################################################*/
4406 /*################################################################################################*/
4407 
4408 static void
4409 printableString ( char *sOutput, int iOutputLen, const char *sInput, int iInputLen )
4410 {
4411 	const char	*printableControlChar[] = {
4412 			"<NUL>", "<SOH>", "<STX>", "<ETX>",
4413 			"<EOT>", "<ENQ>", "<ACK>", "<BEL>",
4414 			"<BS>" , "<HT>" , "<LF>" , "<VT>" ,
4415 			"<FF>" , "<CR>" , "<SO>" , "<SI>" ,
4416 			"<DLE>", "<DC1>", "<DC2>", "<DC3>",
4417 			"<DC4>", "<NAK>", "<SYN>", "<ETB>",
4418 			"<CAN>", "<EM>" , "<SUB>", "<ESC>",
4419 			"<FS>" , "<GS>" , "<RS>" , "<US>" ,
4420 			" " } ;
4421 
4422 	size_t	i, j, n ;
4423 	size_t	InputLen;
4424 	size_t	OutputLen;
4425 
4426 	InputLen = (size_t)iInputLen;
4427 	OutputLen = (size_t)iOutputLen;
4428 	for ( i = j = 0 ; i < InputLen && j < OutputLen ; i ++ ) {
4429 		if ( isprint( (unsigned char)sInput[i] ) ) {
4430 			n = 1 ;
4431 			if ( j + 1 >= OutputLen )
4432 				break ;
4433 			sOutput[j] = sInput[i] ;
4434 		} else if ( ( sInput[i] & 0xFF ) <
4435 			    COUNTOF(printableControlChar) ) {
4436 			n = strlen( printableControlChar[sInput[i] & 0xFF] ) ;
4437 			if ( j + n + 1 >= OutputLen )
4438 				break ;
4439 			strlcpy( sOutput + j,
4440 				 printableControlChar[sInput[i] & 0xFF],
4441 				 OutputLen - j ) ;
4442 		} else {
4443 			n = 5 ;
4444 			if ( j + n + 1 >= OutputLen )
4445 				break ;
4446 			snprintf( sOutput + j, OutputLen - j, "<x%X>",
4447 				  sInput[i] & 0xFF ) ;
4448 		}
4449 		j += n ;
4450 	}
4451 
4452 	sOutput[min(j, (size_t)iOutputLen - 1)] = '\0' ;
4453 
4454 }
4455 
4456 /**************************************************************************************************/
4457 
4458 #else
4459 int refclock_jjy_bs ;
4460 #endif /* REFCLOCK */
4461