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