xref: /netbsd-src/external/bsd/ntp/dist/ntpd/refclock_jjy.c (revision 7d3af8c6a2070d16ec6d1aef203d052d6683100d)
1 /*	$NetBSD: refclock_jjy.c,v 1.4 2012/02/01 20:48:01 kardel Exp $	*/
2 
3 /*
4  * refclock_jjy - clock driver for JJY receivers
5  */
6 
7 /**********************************************************************/
8 /*								      */
9 /*  Copyright (C) 2001-2004, 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 /**********************************************************************/
98 
99 #ifdef HAVE_CONFIG_H
100 #include <config.h>
101 #endif
102 
103 #if defined(REFCLOCK) && defined(CLOCK_JJY)
104 
105 #include <stdio.h>
106 #include <ctype.h>
107 #include <string.h>
108 #include <sys/time.h>
109 #include <time.h>
110 
111 #include "ntpd.h"
112 #include "ntp_io.h"
113 #include "ntp_tty.h"
114 #include "ntp_refclock.h"
115 #include "ntp_calendar.h"
116 #include "ntp_stdlib.h"
117 
118 /**********************************************************************/
119 /*								      */
120 /*  The Tristate Ltd. JJY receiver JJY01			      */
121 /*								      */
122 /*  Command	   Response		    Remarks		      */
123 /*  ------------   ----------------------   ---------------------     */
124 /*  dcst<CR><LF>   VALID|INVALID<CR><LF>			      */
125 /*  stus<CR><LF>   ADJUSTED|UNADJUSTED<CR><LF>			      */
126 /*  date<CR><LF>   YYYY/MM/DD XXX<CR><LF>			      */
127 /*  time<CR><LF>   HH:MM:SS<CR><LF>				      */
128 /*  stim<CR><LF>   HH:MM:SS<CR><LF>	    Reply at just second      */
129 /*								      */
130 /*  During synchronization after a receiver is turned on,	      */
131 /*  It replies the past time from 2000/01/01 00:00:00.		      */
132 /*  The function "refclock_process" checks the time and tells	      */
133 /*  as an insanity time.					      */
134 /*								      */
135 /**********************************************************************/
136 /*								      */
137 /*  The C-DEX Co. Ltd. JJY receiver JST2000			      */
138 /*								      */
139 /*  Command	   Response		    Remarks		      */
140 /*  ------------   ----------------------   ---------------------     */
141 /*  <ENQ>1J<ETX>   <STX>JYYMMDD HHMMSSS<ETX>			      */
142 /*								      */
143 /**********************************************************************/
144 /*								      */
145 /*  The Echo Keisokuki Co. Ltd. JJY receiver LT2000		      */
146 /*								      */
147 /*  Command        Response		    Remarks		      */
148 /*  ------------   ----------------------   ---------------------     */
149 /*  #					    Mode 1 (Request&Send)     */
150 /*  T		   YYMMDDWHHMMSS<BCC1><BCC2><CR>		      */
151 /*  C					    Mode 2 (Continuous)	      */
152 /*		   YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR>	      */
153 /*		   <SUB>		    Second signal	      */
154 /*								      */
155 /**********************************************************************/
156 /*								      */
157 /*  The CITIZEN T.I.C CO., LTD. JJY receiver JJY200		      */
158 /*								      */
159 /*  Command	   Response		    Remarks		      */
160 /*  ------------   ----------------------   ---------------------     */
161 /*		   'XX YY/MM/DD W HH:MM:SS<CR>			      */
162 /*					    XX: OK|NG|ER	      */
163 /*					    W:  0(Monday)-6(Sunday)   */
164 /*								      */
165 /**********************************************************************/
166 
167 /*
168  * Interface definitions
169  */
170 #define	DEVICE  	"/dev/jjy%d"	/* device name and unit */
171 #define	SPEED232	B9600		/* uart speed (9600 baud) */
172 #define	SPEED232_TRISTATE_JJY01		B9600   /* UART speed (9600 baud) */
173 #define	SPEED232_CDEX_JST2000		B9600   /* UART speed (9600 baud) */
174 #define	SPEED232_ECHOKEISOKUKI_LT2000	B9600   /* UART speed (9600 baud) */
175 #define	SPEED232_CITIZENTIC_JJY200	B4800   /* UART speed (4800 baud) */
176 #define	REFID   	"JJY"		/* reference ID */
177 #define	DESCRIPTION	"JJY Receiver"
178 #define	PRECISION	(-3)		/* precision assumed (about 100 ms) */
179 
180 /*
181  * JJY unit control structure
182  */
183 struct jjyunit {
184 	char	unittype ;	    /* UNITTYPE_XXXXXXXXXX */
185 	short   operationmode ;	    /* Echo Keisokuki LT-2000 : 1 or 2 */
186 	short	version ;
187 	short	linediscipline ;    /* LDISC_CLK or LDISC_RAW */
188 	char    bPollFlag ;	    /* Set by jjy_pool and Reset by jjy_receive */
189 	int 	linecount ;
190 	int 	lineerror ;
191 	int 	year, month, day, hour, minute, second, msecond ;
192 /* LDISC_RAW only */
193 #define	MAX_LINECOUNT	8
194 #define	MAX_RAWBUF   	64
195 	int 	lineexpect ;
196 	int 	charexpect [ MAX_LINECOUNT ] ;
197 	int 	charcount ;
198 	char	rawbuf [ MAX_RAWBUF ] ;
199 };
200 
201 #define	UNITTYPE_TRISTATE_JJY01	1
202 #define	UNITTYPE_CDEX_JST2000  	2
203 #define	UNITTYPE_ECHOKEISOKUKI_LT2000  	3
204 #define	UNITTYPE_CITIZENTIC_JJY200  	4
205 
206 /*
207  * Function prototypes
208  */
209 static	int 	jjy_start		    (int, struct peer *);
210 static	void	jjy_shutdown		    (int, struct peer *);
211 static	void	jjy_poll		    (int, struct peer *);
212 static	void	jjy_poll_tristate_jjy01	    (int, struct peer *);
213 static	void	jjy_poll_cdex_jst2000	    (int, struct peer *);
214 static	void	jjy_poll_echokeisokuki_lt2000(int, struct peer *);
215 static	void	jjy_poll_citizentic_jjy200  (int, struct peer *);
216 static	void	jjy_receive		    (struct recvbuf *);
217 static	int	jjy_receive_tristate_jjy01  (struct recvbuf *);
218 static	int	jjy_receive_cdex_jst2000    (struct recvbuf *);
219 static	int	jjy_receive_echokeisokuki_lt2000 (struct recvbuf *);
220 static  int	jjy_receive_citizentic_jjy200 (struct recvbuf *);
221 
222 static	void	printableString ( char*, int, char*, int ) ;
223 
224 /*
225  * Transfer vector
226  */
227 struct	refclock refclock_jjy = {
228 	jjy_start,	/* start up driver */
229 	jjy_shutdown,	/* shutdown driver */
230 	jjy_poll,	/* transmit poll message */
231 	noentry,	/* not used */
232 	noentry,	/* not used */
233 	noentry,	/* not used */
234 	NOFLAGS		/* not used */
235 };
236 
237 /*
238  * Start up driver return code
239  */
240 #define	RC_START_SUCCESS	1
241 #define	RC_START_ERROR		0
242 
243 /*
244  * Local constants definition
245  */
246 
247 #define	MAX_LOGTEXT	64
248 
249 /*
250  * Tristate JJY01/JJY02 constants definition
251  */
252 
253 #define	TS_JJY01_COMMAND_NUMBER_DATE	1
254 #define	TS_JJY01_COMMAND_NUMBER_TIME	2
255 #define	TS_JJY01_COMMAND_NUMBER_STIM	3
256 #define	TS_JJY01_COMMAND_NUMBER_STUS	4
257 #define	TS_JJY01_COMMAND_NUMBER_DCST	5
258 
259 #define	TS_JJY01_REPLY_DATE		"yyyy/mm/dd www\r\n"
260 #define	TS_JJY01_REPLY_STIM		"hh:mm:ss\r\n"
261 #define	TS_JJY01_REPLY_STUS_YES		"adjusted\r\n"
262 #define	TS_JJY01_REPLY_STUS_NO		"unadjusted\r\n"
263 #define	TS_JJY01_REPLY_DCST_VALID	"valid\r\n"
264 #define	TS_JJY01_REPLY_DCST_INVALID	"invalid\r\n"
265 
266 #define	TS_JJY01_REPLY_LENGTH_DATE	    14	/* Length without <CR><LF> */
267 #define	TS_JJY01_REPLY_LENGTH_STIM	    8	/* Length without <CR><LF> */
268 #define	TS_JJY01_REPLY_LENGTH_STUS_YES	    8	/* Length without <CR><LF> */
269 #define	TS_JJY01_REPLY_LENGTH_STUS_NO	    10	/* Length without <CR><LF> */
270 #define	TS_JJY01_REPLY_LENGTH_DCST_VALID    5	/* Length without <CR><LF> */
271 #define	TS_JJY01_REPLY_LENGTH_DCST_INVALID  7	/* Length without <CR><LF> */
272 
273 static  struct
274 {
275 	const char	commandNumber ;
276 	const char	*commandLog ;
277 	const char	*command ;
278 	int	commandLength ;
279 } tristate_jjy01_command_sequence[] =
280 {
281 	/* dcst<CR><LF> -> VALID<CR><LF> or INVALID<CR><LF> */
282 	{ TS_JJY01_COMMAND_NUMBER_DCST, "dcst", "dcst\r\n", 6 },
283 	/* stus<CR><LF> -> ADJUSTED<CR><LF> or UNADJUSTED<CR><LF> */
284 	{ TS_JJY01_COMMAND_NUMBER_STUS, "stus", "stus\r\n", 6 },
285 	/* date<CR><LF> -> YYYY/MM/DD WWW<CR><LF> */
286 	{ TS_JJY01_COMMAND_NUMBER_DATE, "date", "date\r\n", 6 },
287 	/* stim<CR><LF> -> HH:MM:SS<CR><LF> */
288 	{ TS_JJY01_COMMAND_NUMBER_STIM, "stim", "stim\r\n", 6 },
289 	{ 0			      , NULL  , NULL	  , 0 }
290 } ;
291 
292 
293 /**************************************************************************************************/
294 /*  jjy_start - open the devices and initialize data for processing                               */
295 /**************************************************************************************************/
296 static int
297 jjy_start ( int unit, struct peer *peer )
298 {
299 
300 	struct jjyunit	    *up ;
301 	struct refclockproc *pp ;
302 	int 	fd ;
303 	char	*pDeviceName ;
304 	short	iDiscipline ;
305 	int 	iSpeed232 ;
306 
307 #ifdef DEBUG
308 	if ( debug ) {
309 		printf ( "jjy_start (refclock_jjy.c) : %s  mode=%d  ", ntoa(&peer->srcadr), peer->ttl ) ;
310 		printf ( DEVICE, unit ) ;
311 		printf ( "\n" ) ;
312 	}
313 #endif
314 	/*
315 	 * Open serial port
316 	 */
317 	pDeviceName = emalloc ( strlen(DEVICE) + 10 );
318 	snprintf ( pDeviceName, strlen(DEVICE) + 10, DEVICE, unit ) ;
319 
320 	/*
321 	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
322 	 */
323 	switch ( peer->ttl ) {
324 	case 0 :
325 	case 1 :
326 		iDiscipline = LDISC_CLK ;
327 		iSpeed232   = SPEED232_TRISTATE_JJY01 ;
328 		break ;
329 	case 2 :
330 		iDiscipline = LDISC_RAW ;
331 		iSpeed232   = SPEED232_CDEX_JST2000   ;
332 		break ;
333 	case 3 :
334 		iDiscipline = LDISC_CLK ;
335 		iSpeed232   = SPEED232_ECHOKEISOKUKI_LT2000 ;
336 		break ;
337 	case 4 :
338 		iDiscipline = LDISC_CLK ;
339 		iSpeed232   = SPEED232_CITIZENTIC_JJY200 ;
340 		break ;
341 	default :
342 		msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
343 			  ntoa(&peer->srcadr), peer->ttl ) ;
344 		free ( (void*) pDeviceName ) ;
345 		return RC_START_ERROR ;
346 	}
347 
348 	if ( ! ( fd = refclock_open ( pDeviceName, iSpeed232, iDiscipline ) ) ) {
349 		free ( (void*) pDeviceName ) ;
350 		return RC_START_ERROR ;
351 	}
352 	free ( (void*) pDeviceName ) ;
353 
354 	/*
355 	 * Allocate and initialize unit structure
356 	 */
357 	up = emalloc (sizeof(*up));
358 	memset ( up, 0, sizeof(*up) ) ;
359 	up->linediscipline = iDiscipline ;
360 
361 	/*
362 	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
363 	 */
364 	switch ( peer->ttl ) {
365 	case 0 :
366 		/*
367 		 * The mode 0 is a default clock type at this time.
368 		 * But this will be change to auto-detect mode in the future.
369 		 */
370 	case 1 :
371 		up->unittype = UNITTYPE_TRISTATE_JJY01 ;
372 		up->version  = 100 ;
373 		/* 2010/11/20 */
374 		/* Command sequence is defined by the struct tristate_jjy01_command_sequence, */
375 		/* and the following 3 lines are not used in the mode LDISC_CLK. */
376 		/* up->lineexpect = 2 ; */
377 		/* up->charexpect[0] = 14 ; */ /* YYYY/MM/DD WWW<CR><LF> */
378 		/* up->charexpect[1] =  8 ; */ /* HH:MM:SS<CR><LF> */
379 		break ;
380 	case 2 :
381 		up->unittype = UNITTYPE_CDEX_JST2000 ;
382 		up->lineexpect = 1 ;
383 		up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
384 		break ;
385 	case 3 :
386 		up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
387 		up->operationmode = 2 ;  /* Mode 2 : Continuous mode */
388 		up->lineexpect = 1 ;
389 		switch ( up->operationmode ) {
390 		case 1 :
391 			up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
392 			break ;
393 		case 2 :
394 			up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
395 			break ;
396 		}
397 		break ;
398 	case 4 :
399 		up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
400 		up->lineexpect = 1 ;
401 		up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
402 		break ;
403 
404 	/* 2010/11/20 */
405 	/* The "default:" section of this switch block is never executed,     */
406 	/* because the former switch block traps the same "default:" case.    */
407 	/* This "default:" section codes are removed to avoid spending time   */
408 	/* in the future looking, though the codes are functionally harmless. */
409 
410 	}
411 
412 	pp = peer->procptr ;
413 	pp->unitptr       = (caddr_t) up ;
414 	pp->io.clock_recv = jjy_receive ;
415 	pp->io.srcclock   = (caddr_t) peer ;
416 	pp->io.datalen	  = 0 ;
417 	pp->io.fd	  = fd ;
418 	if ( ! io_addclock(&pp->io) ) {
419 		close ( fd ) ;
420 		pp->io.fd = -1 ;
421 		free ( up ) ;
422 		pp->unitptr = NULL ;
423 		return RC_START_ERROR ;
424 	}
425 
426 	/*
427 	 * Initialize miscellaneous variables
428 	 */
429 	peer->precision = PRECISION ;
430 	peer->burst	= 1 ;
431 	pp->clockdesc	= DESCRIPTION ;
432 	memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
433 
434 	return RC_START_SUCCESS ;
435 
436 }
437 
438 
439 /**************************************************************************************************/
440 /*  jjy_shutdown - shutdown the clock                                                             */
441 /**************************************************************************************************/
442 static void
443 jjy_shutdown ( int unit, struct peer *peer )
444 {
445 
446 	struct jjyunit	    *up;
447 	struct refclockproc *pp;
448 
449 	pp = peer->procptr ;
450 	up = (struct jjyunit *) pp->unitptr ;
451 	if ( -1 != pp->io.fd )
452 		io_closeclock ( &pp->io ) ;
453 	if ( NULL != up )
454 		free ( up ) ;
455 
456 }
457 
458 
459 /**************************************************************************************************/
460 /*  jjy_receive - receive data from the serial interface                                          */
461 /**************************************************************************************************/
462 static void
463 jjy_receive ( struct recvbuf *rbufp )
464 {
465 
466 	struct jjyunit	    *up ;
467 	struct refclockproc *pp ;
468 	struct peer	    *peer;
469 
470 	l_fp	tRecvTimestamp;		/* arrival timestamp */
471 	int 	rc ;
472 	char	sLogText [ MAX_LOGTEXT ] ;
473 	int 	i, bCntrlChar ;
474 
475 	/*
476 	 * Initialize pointers and read the timecode and timestamp
477 	 */
478 	peer = (struct peer *) rbufp->recv_srcclock ;
479 	pp = peer->procptr ;
480 	up = (struct jjyunit *) pp->unitptr ;
481 
482 	/*
483 	 * Get next input line
484 	 */
485 	pp->lencode  = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
486 
487 	if ( up->linediscipline == LDISC_RAW ) {
488 		/*
489 		 * The reply with <STX> and <ETX> may give a blank line
490 		 */
491 		if ( pp->lencode == 0  &&  up->charcount == 0 ) return ;
492 		/*
493 		 * Copy received charaters to temporary buffer
494 		 */
495 		for ( i = 0 ;
496 		      i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ;
497 		      i ++ , up->charcount ++ ) {
498 			up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
499 		}
500 		while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
501 			for ( i = 0 ; i < up->charcount - 1 ; i ++ )
502 				up->rawbuf[i] = up->rawbuf[i+1] ;
503 			up->charcount -- ;
504 		}
505 		bCntrlChar = 0 ;
506 		for ( i = 0 ; i < up->charcount ; i ++ ) {
507 			if ( up->rawbuf[i] < ' ' ) {
508 				bCntrlChar = 1 ;
509 				break ;
510 			}
511 		}
512 		if ( pp->lencode > 0  &&  up->linecount < up->lineexpect ) {
513 			if ( bCntrlChar == 0  &&
514 			     up->charcount < up->charexpect[up->linecount] )
515 				return ;
516 		}
517 		up->rawbuf[up->charcount] = 0 ;
518 	} else {
519 		/*
520 		 * The reply with <CR><LF> gives a blank line
521 		 */
522 		if ( pp->lencode == 0 ) return ;
523 	}
524 	/*
525 	 * We get down to business
526 	 */
527 
528 	pp->lastrec = tRecvTimestamp ;
529 
530 	up->linecount ++ ;
531 
532 	if ( up->lineerror != 0 ) return ;
533 
534 	switch ( up->unittype ) {
535 
536 	case UNITTYPE_TRISTATE_JJY01 :
537 		rc = jjy_receive_tristate_jjy01  ( rbufp ) ;
538 		break ;
539 
540 	case UNITTYPE_CDEX_JST2000 :
541 		rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
542 		break ;
543 
544 	case UNITTYPE_ECHOKEISOKUKI_LT2000 :
545 		rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
546 		break ;
547 
548 	case UNITTYPE_CITIZENTIC_JJY200 :
549 		rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
550 		break ;
551 
552 	default :
553 		rc = 0 ;
554 		break ;
555 
556 	}
557 
558 	if ( up->linediscipline == LDISC_RAW ) {
559 		if ( up->linecount <= up->lineexpect  &&
560 		     up->charcount > up->charexpect[up->linecount-1] ) {
561 			for ( i = 0 ;
562 			      i < up->charcount - up->charexpect[up->linecount-1] ;
563 			      i ++ ) {
564 				up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
565 			}
566 			up->charcount -= up->charexpect[up->linecount-1] ;
567 		} else {
568 			up->charcount = 0 ;
569 		}
570 	}
571 
572 	if ( rc == 0 )
573 		return ;
574 
575 	up->bPollFlag = 0 ;
576 
577 	if ( up->lineerror != 0 ) {
578 		refclock_report ( peer, CEVNT_BADREPLY ) ;
579 		strncpy  ( sLogText, "BAD REPLY [",
580 			   sizeof( sLogText ) ) ;
581 		if ( up->linediscipline == LDISC_RAW ) {
582 			strncat ( sLogText, up->rawbuf,
583 				  sizeof( sLogText ) -
584 				      strlen ( sLogText ) - 1 ) ;
585 		} else {
586 			strncat ( sLogText, pp->a_lastcode,
587 				  sizeof( sLogText ) -
588 				      strlen ( sLogText ) - 1 ) ;
589 		}
590 		sLogText[MAX_LOGTEXT-1] = 0 ;
591 		if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 )
592 			strncat ( sLogText, "]",
593 				  sizeof( sLogText ) -
594 				      strlen ( sLogText ) - 1 ) ;
595 		record_clock_stats ( &peer->srcadr, sLogText ) ;
596 		return ;
597 	}
598 
599 	pp->year   = up->year ;
600 	pp->day    = ymd2yd ( up->year, up->month, up->day ) ;
601 	pp->hour   = up->hour ;
602 	pp->minute = up->minute ;
603 	pp->second = up->second ;
604 	pp->nsec   = up->msecond * 1000000;
605 
606 	/*
607 	 * JST to UTC
608 	 */
609 	pp->hour -= 9 ;
610 	if ( pp->hour < 0 ) {
611 		pp->hour += 24 ;
612 		pp->day -- ;
613 		if ( pp->day < 1 ) {
614 			pp->year -- ;
615 			pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
616 		}
617 	}
618 #ifdef DEBUG
619 	if ( debug ) {
620 		printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST   ",
621 			  up->year, up->month, up->day, up->hour,
622 			  up->minute, up->second, up->msecond/100 ) ;
623 		printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
624 			  pp->year, pp->day, pp->hour, pp->minute,
625 			  pp->second, (int)(pp->nsec/100000000) ) ;
626 	}
627 #endif
628 
629 	/*
630 	 * Process the new sample in the median filter and determine the
631 	 * timecode timestamp.
632 	 */
633 
634 	snprintf ( sLogText, sizeof(sLogText),
635 		   "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
636 		   up->year, up->month, up->day,
637 		   up->hour, up->minute, up->second, up->msecond/100 ) ;
638 	record_clock_stats ( &peer->srcadr, sLogText ) ;
639 
640 	if ( ! refclock_process ( pp ) ) {
641 		refclock_report(peer, CEVNT_BADTIME);
642 		return ;
643 	}
644 
645 	pp->lastref = pp->lastrec;
646 	refclock_receive(peer);
647 
648 }
649 
650 /**************************************************************************************************/
651 
652 static int
653 jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
654 {
655 
656 	static	const char	*sFunctionName = "jjy_receive_tristate_jjy01" ;
657 
658 	struct jjyunit	    *up ;
659 	struct refclockproc *pp ;
660 	struct peer	    *peer;
661 
662 	char	*pBuf ;
663 	int 	iLen ;
664 	int 	rc ;
665 
666 	int 	bOverMidnight = 0 ;
667 
668 	char	sLogText [ MAX_LOGTEXT ], sReplyText  [ MAX_LOGTEXT ] ;
669 
670 	const char *pCmd ;
671 	int 	iCmdLen ;
672 
673 	/*
674 	 * Initialize pointers and read the timecode and timestamp
675 	 */
676 	peer = (struct peer *) rbufp->recv_srcclock ;
677 	pp = peer->procptr ;
678 	up = (struct jjyunit *) pp->unitptr ;
679 
680 	if ( up->linediscipline == LDISC_RAW ) {
681 		pBuf = up->rawbuf ;
682 		iLen = up->charcount ;
683 	} else {
684 		pBuf = pp->a_lastcode ;
685 		iLen = pp->lencode ;
686 	}
687 
688 	switch ( tristate_jjy01_command_sequence[up->linecount-1].commandNumber ) {
689 
690 	case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */
691 
692 		if ( iLen != TS_JJY01_REPLY_LENGTH_DATE ) {
693 			up->lineerror = 1 ;
694 			break ;
695 		}
696 
697 		rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year,
698 			      &up->month, &up->day ) ;
699 		if ( rc != 3 || up->year < 2000 || up->month < 1 ||
700 		     up->month > 12 || up->day < 1 || up->day > 31 ) {
701 			up->lineerror = 1 ;
702 			break ;
703 		}
704 
705 		/*** Start of modification on 2004/10/31 ***/
706 		/*
707 		 * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
708 		 * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
709 		 * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
710 		 * so this driver issues the second command "stim" after the reply of the first command "date".
711 		 */
712 
713 		/*** 2010/11/20 ***/
714 		/*
715 		 * Codes of a next command issue are moved to the end of this function.
716 		 */
717 
718 		/*** End of modification ***/
719 
720 		break ;
721 
722 	case TS_JJY01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
723 	case TS_JJY01_COMMAND_NUMBER_STIM : /* HH:MM:SS */
724 
725 		if ( iLen != TS_JJY01_REPLY_LENGTH_STIM ) {
726 			up->lineerror = 1 ;
727 			break ;
728 		}
729 
730 		rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour,
731 			      &up->minute, &up->second ) ;
732 		if ( rc != 3 || up->hour > 23 || up->minute > 59 ||
733 		     up->second > 60 ) {
734 			up->lineerror = 1 ;
735 			break ;
736 		}
737 
738 		up->msecond = 0 ;
739 		if ( up->hour == 0 && up->minute == 0 &&
740 		     up->second <= 2 ) {
741 			/*
742 			 * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver separately,
743 			 * and the JJY receiver replies a date and time separately.
744 			 * Just after midnight transitions, we ignore this time.
745 			 */
746 			bOverMidnight = 1 ;
747 		}
748 		break ;
749 
750 	case TS_JJY01_COMMAND_NUMBER_STUS :
751 
752 		if ( ( iLen == TS_JJY01_REPLY_LENGTH_STUS_YES
753 		    && strncmp( pBuf, TS_JJY01_REPLY_STUS_YES,
754 				TS_JJY01_REPLY_LENGTH_STUS_YES ) == 0 )
755 		  || ( iLen == TS_JJY01_REPLY_LENGTH_STUS_NO
756 		    && strncmp( pBuf, TS_JJY01_REPLY_STUS_NO,
757 				TS_JJY01_REPLY_LENGTH_STUS_NO ) == 0 ) ) {
758 			/* Good */
759 		} else {
760 			up->lineerror = 1 ;
761 			break ;
762 		}
763 
764 		break ;
765 
766 	case TS_JJY01_COMMAND_NUMBER_DCST :
767 
768 		if ( ( iLen == TS_JJY01_REPLY_LENGTH_DCST_VALID
769 		    && strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID,
770 				TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0 )
771 		  || ( iLen == TS_JJY01_REPLY_LENGTH_DCST_INVALID
772 		    && strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID,
773 				TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) ) {
774 			/* Good */
775 		} else {
776 			up->lineerror = 1 ;
777 			break ;
778 		}
779 
780 		break ;
781 
782 	default : /*  Unexpected reply */
783 
784 		up->lineerror = 1 ;
785 		break ;
786 
787 	}
788 
789 	/* Clockstats Log */
790 
791 	printableString( sReplyText, sizeof(sReplyText), pBuf, iLen ) ;
792 	snprintf ( sLogText, sizeof(sLogText), "%d: %s -> %c: %s",
793 		   up->linecount,
794 		   tristate_jjy01_command_sequence[up->linecount-1].commandLog,
795 		   ( up->lineerror == 0 )
796 			? ( ( bOverMidnight == 0 )
797 				? 'O'
798 				: 'S' )
799 			: 'X',
800 		   sReplyText ) ;
801 	record_clock_stats ( &peer->srcadr, sLogText ) ;
802 
803 	/* Check before issue next command */
804 
805 	if ( up->lineerror != 0 ) {
806 		/* Do not issue next command */
807 		return 0 ;
808 	}
809 
810 	if ( bOverMidnight != 0 ) {
811 		/* Do not issue next command */
812 		return 0 ;
813 	}
814 
815 	if ( tristate_jjy01_command_sequence[up->linecount].command == NULL ) {
816 		/* Command sequence completed */
817 		return 1 ;
818 	}
819 
820 	/* Issue next command */
821 
822 #ifdef DEBUG
823 	if ( debug ) {
824 		printf ( "%s (refclock_jjy.c) : send '%s'\n",
825 			sFunctionName, tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
826 	}
827 #endif
828 
829 	pCmd =  tristate_jjy01_command_sequence[up->linecount].command ;
830 	iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
831 	if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
832 		refclock_report ( peer, CEVNT_FAULT ) ;
833 	}
834 
835 	return 0 ;
836 
837 }
838 
839 /**************************************************************************************************/
840 
841 static int
842 jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
843 {
844 	static	const char	*sFunctionName = "jjy_receive_cdex_jst2000" ;
845 
846 	struct jjyunit      *up ;
847 	struct refclockproc *pp ;
848 	struct peer         *peer;
849 
850 	char	*pBuf ;
851 	int 	iLen ;
852 	int 	rc ;
853 
854 	/*
855 	 * Initialize pointers and read the timecode and timestamp
856 	 */
857 	peer = (struct peer *) rbufp->recv_srcclock ;
858 	pp = peer->procptr ;
859 	up = (struct jjyunit *) pp->unitptr ;
860 
861 	if ( up->linediscipline == LDISC_RAW ) {
862 		pBuf = up->rawbuf ;
863 		iLen = up->charcount ;
864 	} else {
865 		pBuf = pp->a_lastcode ;
866 		iLen = pp->lencode ;
867 	}
868 
869 	switch ( up->linecount ) {
870 
871 	case 1 : /* JYYMMDD HHMMSSS */
872 
873 		if ( iLen != 15 ) {
874 #ifdef DEBUG
875 			if ( debug >= 2 ) {
876 				printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
877 					 sFunctionName, iLen ) ;
878 			}
879 #endif
880 			up->lineerror = 1 ;
881 			break ;
882 		}
883 		rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
884 			      &up->year, &up->month, &up->day,
885 			      &up->hour, &up->minute, &up->second,
886 			      &up->msecond ) ;
887 		if ( rc != 7 || up->month < 1 || up->month > 12 ||
888 		     up->day < 1 || up->day > 31 || up->hour > 23 ||
889 		     up->minute > 59 || up->second > 60 ) {
890 #ifdef DEBUG
891 			if ( debug >= 2 ) {
892 				printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n",
893 					 sFunctionName, rc, up->year,
894 					 up->month, up->day, up->hour,
895 					 up->minute, up->second,
896 					 up->msecond ) ;
897 			}
898 #endif
899 			up->lineerror = 1 ;
900 			break ;
901 		}
902 		up->year    += 2000 ;
903 		up->msecond *= 100 ;
904 		break ;
905 
906 	default : /*  Unexpected reply */
907 
908 		up->lineerror = 1 ;
909 		break ;
910 
911 	}
912 
913 	return 1 ;
914 
915 }
916 
917 /**************************************************************************************************/
918 
919 static int
920 jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
921 {
922 	static	const char	*sFunctionName = "jjy_receive_echokeisokuki_lt2000" ;
923 
924 	struct jjyunit      *up ;
925 	struct refclockproc *pp ;
926 	struct peer	    *peer;
927 
928 	char	*pBuf ;
929 	int 	iLen ;
930 	int 	rc ;
931 	int	i, ibcc, ibcc1, ibcc2 ;
932 
933 	/*
934 	 * Initialize pointers and read the timecode and timestamp
935 	 */
936 	peer = (struct peer *) rbufp->recv_srcclock ;
937 	pp = peer->procptr ;
938 	up = (struct jjyunit *) pp->unitptr ;
939 
940 	if ( up->linediscipline == LDISC_RAW ) {
941 		pBuf = up->rawbuf ;
942 		iLen = up->charcount ;
943 	} else {
944 		pBuf = pp->a_lastcode ;
945 		iLen = pp->lencode ;
946 	}
947 
948 	switch ( up->linecount ) {
949 
950 	case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
951 
952 		if ( ( up->operationmode == 1 && iLen != 15 ) ||
953 		     ( up->operationmode == 2 && iLen != 17 ) ) {
954 #ifdef DEBUG
955 			if ( debug >= 2 ) {
956 				printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
957 					 sFunctionName, iLen ) ;
958 			}
959 #endif
960 			if ( up->operationmode == 1 ) {
961 #ifdef DEBUG
962 				if ( debug ) {
963 					printf ( "%s (refclock_jjy.c) : send '#'\n", __func__ ) ;
964 				}
965 #endif
966 				if ( write ( pp->io.fd, "#",1 ) != 1  ) {
967 					refclock_report ( peer, CEVNT_FAULT ) ;
968 				}
969 			}
970 			up->lineerror = 1 ;
971 			break ;
972 		}
973 
974 		if ( up->operationmode == 1 ) {
975 
976 			for ( i = ibcc = 0 ; i < 13 ; i ++ )
977 				ibcc ^= pBuf[i] ;
978 			ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
979 			ibcc2 = 0x30 | ( ( ibcc      ) & 0xF ) ;
980 			if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
981 #ifdef DEBUG
982 				if ( debug >= 2 ) {
983 					printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n",
984 						 sFunctionName,
985 						 pBuf[13] & 0xFF,
986 						 pBuf[14] & 0xFF,
987 						 ibcc1, ibcc2 ) ;
988 				}
989 #endif
990 				up->lineerror = 1 ;
991 				break ;
992 			}
993 
994 		}
995 
996 		rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
997 			      &up->year, &up->month, &up->day,
998 			      &up->hour, &up->minute, &up->second ) ;
999 		if ( rc != 6 || up->month < 1 || up->month > 12 ||
1000 		     up->day < 1 || up->day > 31 || up->hour > 23 ||
1001 		     up->minute > 59 || up->second > 60 ) {
1002 #ifdef DEBUG
1003 			if ( debug >= 2 ) {
1004 				printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n",
1005 					 sFunctionName, rc, up->year,
1006 					 up->month, up->day, up->hour,
1007 					 up->minute, up->second ) ;
1008 			}
1009 #endif
1010 			up->lineerror = 1 ;
1011 			break ;
1012 		}
1013 
1014 		up->year += 2000 ;
1015 
1016 		if ( up->operationmode == 2 ) {
1017 
1018 			/* A time stamp comes on every 0.5 seccond in the mode 2 of the LT-2000. */
1019 			up->msecond = 500 ;
1020 			pp->second -- ;
1021 			if ( pp->second < 0 ) {
1022 				pp->second = 59 ;
1023 				pp->minute -- ;
1024 				if ( pp->minute < 0 ) {
1025 					pp->minute = 59 ;
1026 					pp->hour -- ;
1027 					if ( pp->hour < 0 ) {
1028 						pp->hour = 23 ;
1029 						pp->day -- ;
1030 						if ( pp->day < 1 ) {
1031 							pp->year -- ;
1032 							pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
1033 						}
1034 					}
1035 				}
1036 			}
1037 
1038 			/* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
1039 #ifdef DEBUG
1040 			if ( debug ) {
1041 				printf ( "%s (refclock_jjy.c) : send '#'\n",
1042 					 sFunctionName ) ;
1043 			}
1044 #endif
1045 			if ( write ( pp->io.fd, "#",1 ) != 1  ) {
1046 				refclock_report ( peer, CEVNT_FAULT ) ;
1047 			}
1048 
1049 		}
1050 
1051 		break ;
1052 
1053 	default : /*  Unexpected reply */
1054 
1055 #ifdef DEBUG
1056 		if ( debug ) {
1057 			printf ( "%s (refclock_jjy.c) : send '#'\n",
1058 				 sFunctionName ) ;
1059 		}
1060 #endif
1061 		if ( write ( pp->io.fd, "#",1 ) != 1  ) {
1062 			refclock_report ( peer, CEVNT_FAULT ) ;
1063 		}
1064 
1065 		up->lineerror = 1 ;
1066 		break ;
1067 
1068 	}
1069 
1070 	return 1 ;
1071 
1072 }
1073 
1074 /**************************************************************************************************/
1075 
1076 static int
1077 jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
1078 {
1079 
1080 	static const char *sFunctionName = "jjy_receive_citizentic_jjy200" ;
1081 
1082 	struct jjyunit		*up ;
1083 	struct refclockproc	*pp ;
1084 	struct peer		*peer;
1085 
1086 	char	*pBuf ;
1087 	int	iLen ;
1088 	int	rc ;
1089 	char	cApostrophe, sStatus[3] ;
1090 	int	iWeekday ;
1091 
1092 	/*
1093 	* Initialize pointers and read the timecode and timestamp
1094 	*/
1095 	peer = (struct peer *) rbufp->recv_srcclock ;
1096 	pp = peer->procptr ;
1097 	up = (struct jjyunit *) pp->unitptr ;
1098 
1099 	if ( up->linediscipline == LDISC_RAW ) {
1100 		pBuf = up->rawbuf ;
1101 		iLen = up->charcount ;
1102 	} else {
1103 		pBuf = pp->a_lastcode ;
1104 		iLen = pp->lencode ;
1105 	}
1106 
1107 	/*
1108 	* JJY-200 sends a timestamp every second.
1109 	* So, a timestamp is ignored unless it is right after polled.
1110 	*/
1111 	if ( ! up->bPollFlag )
1112 		return 0 ;
1113 
1114 	switch ( up->linecount ) {
1115 
1116 	case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
1117 
1118 		if ( iLen != 23 ) {
1119 #ifdef DEBUG
1120 			if ( debug >= 2 ) {
1121 				printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
1122 					 sFunctionName, iLen ) ;
1123 			}
1124 #endif
1125 			up->lineerror = 1 ;
1126 			break ;
1127 		}
1128 
1129 		rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
1130 			      &cApostrophe, sStatus, &up->year,
1131 			      &up->month, &up->day, &iWeekday,
1132 			      &up->hour, &up->minute, &up->second ) ;
1133 		sStatus[2] = 0 ;
1134 		if ( rc != 9 || cApostrophe != '\'' ||
1135 		     strcmp( sStatus, "OK" ) != 0 || up->month < 1 ||
1136 		     up->month > 12 || up->day < 1 || up->day > 31 ||
1137 		     iWeekday > 6 || up->hour > 23 || up->minute > 59 ||
1138 		     up->second > 60 ) {
1139 #ifdef DEBUG
1140 			if ( debug >= 2 ) {
1141 				printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n",
1142 					 sFunctionName, rc, cApostrophe,
1143 					 sStatus, up->year, up->month,
1144 					 up->day, iWeekday, up->hour,
1145 					 up->minute, up->second ) ;
1146 			}
1147 #endif
1148 			up->lineerror = 1 ;
1149 			break ;
1150 		}
1151 
1152 		up->year += 2000 ;
1153 		up->msecond = 0 ;
1154 
1155 		break ;
1156 
1157 	default : /* Unexpected reply */
1158 
1159 		up->lineerror = 1 ;
1160 		break ;
1161 
1162 	}
1163 
1164 	return 1 ;
1165 
1166 }
1167 
1168 /**************************************************************************************************/
1169 /*  jjy_poll - called by the transmit procedure                                                   */
1170 /**************************************************************************************************/
1171 static void
1172 jjy_poll ( int unit, struct peer *peer )
1173 {
1174 
1175 	struct jjyunit      *up;
1176 	struct refclockproc *pp;
1177 
1178 	pp = peer->procptr;
1179 	up = (struct jjyunit *) pp->unitptr ;
1180 
1181 	if ( pp->polls > 0  &&  up->linecount == 0 ) {
1182 		/*
1183 		 * No reply for last command
1184 		 */
1185 		refclock_report ( peer, CEVNT_TIMEOUT ) ;
1186 	}
1187 
1188 #ifdef DEBUG
1189 	if ( debug ) {
1190 		printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
1191 	}
1192 #endif
1193 
1194 	pp->polls ++ ;
1195 
1196 	up->bPollFlag = 1 ;
1197 	up->linecount = 0 ;
1198 	up->lineerror = 0 ;
1199 	up->charcount = 0 ;
1200 
1201 	switch ( up->unittype ) {
1202 
1203 	case UNITTYPE_TRISTATE_JJY01 :
1204 		jjy_poll_tristate_jjy01  ( unit, peer ) ;
1205 		break ;
1206 
1207 	case UNITTYPE_CDEX_JST2000 :
1208 		jjy_poll_cdex_jst2000 ( unit, peer ) ;
1209 		break ;
1210 
1211 	case UNITTYPE_ECHOKEISOKUKI_LT2000 :
1212 		jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
1213 		break ;
1214 
1215 	case UNITTYPE_CITIZENTIC_JJY200 :
1216 		jjy_poll_citizentic_jjy200 ( unit, peer ) ;
1217 		break ;
1218 
1219 	default :
1220 		break ;
1221 
1222 	}
1223 
1224 }
1225 
1226 /**************************************************************************************************/
1227 
1228 static void
1229 jjy_poll_tristate_jjy01  ( int unit, struct peer *peer )
1230 {
1231 
1232 	static const char *sFunctionName = "jjy_poll_tristate_jjy01" ;
1233 
1234 	struct jjyunit	    *up;
1235 	struct refclockproc *pp;
1236 
1237 	const char *pCmd ;
1238 	int 	iCmdLen ;
1239 
1240 	pp = peer->procptr;
1241 	up = (struct jjyunit *) pp->unitptr ;
1242 
1243 	if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
1244 		up->linecount = 2 ;
1245 	}
1246 
1247 #ifdef DEBUG
1248 	if ( debug ) {
1249 		printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->linecount=%d\n",
1250 			sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
1251 			up->linecount ) ;
1252 	}
1253 #endif
1254 
1255 	/*
1256 	 * Send a first command
1257 	 */
1258 
1259 #ifdef DEBUG
1260 	if ( debug ) {
1261 		printf ( "%s (refclock_jjy.c) : send '%s'\n",
1262 			 sFunctionName,
1263 			 tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
1264 	}
1265 #endif
1266 
1267 	pCmd =  tristate_jjy01_command_sequence[up->linecount].command ;
1268 	iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
1269 	if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
1270 		refclock_report ( peer, CEVNT_FAULT ) ;
1271 	}
1272 
1273 }
1274 
1275 /**************************************************************************************************/
1276 
1277 static void
1278 jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
1279 {
1280 
1281 	struct refclockproc *pp;
1282 
1283 	pp = peer->procptr;
1284 
1285 	/*
1286 	 * Send "<ENQ>1J<ETX>" command
1287 	 */
1288 
1289 #ifdef DEBUG
1290 	if ( debug ) {
1291 		printf ( "jjy_poll_cdex_jst2000 (refclock_jjy.c) : send '<ENQ>1J<ETX>'\n" ) ;
1292 	}
1293 #endif
1294 
1295 	if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4  ) {
1296 		refclock_report ( peer, CEVNT_FAULT ) ;
1297 	}
1298 
1299 }
1300 
1301 /**************************************************************************************************/
1302 
1303 static void
1304 jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
1305 {
1306 
1307 	struct jjyunit      *up;
1308 	struct refclockproc *pp;
1309 
1310 	char	sCmd[2] ;
1311 
1312 	pp = peer->procptr;
1313 	up = (struct jjyunit *) pp->unitptr ;
1314 
1315 	/*
1316 	 * Send "T" or "C" command
1317 	 */
1318 
1319 	switch ( up->operationmode ) {
1320 	case 1 : sCmd[0] = 'T' ; break ;
1321 	case 2 : sCmd[0] = 'C' ; break ;
1322 	}
1323 	sCmd[1] = 0 ;
1324 
1325 #ifdef DEBUG
1326 	if ( debug ) {
1327 		printf ( "jjy_poll_echokeisokuki_lt2000 (refclock_jjy.c) : send '%s'\n", sCmd ) ;
1328 	}
1329 #endif
1330 
1331 	if ( write ( pp->io.fd, sCmd, 1 ) != 1  ) {
1332 		refclock_report ( peer, CEVNT_FAULT ) ;
1333 	}
1334 
1335 }
1336 
1337 /**************************************************************************************************/
1338 
1339 static void
1340 jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
1341 {
1342 
1343 	/* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
1344 
1345 }
1346 
1347 /**************************************************************************************************/
1348 
1349 static void
1350 printableString ( char *sOutput, int iOutputLen, char *sInput, int iInputLen )
1351 {
1352 
1353 	const char	*printableControlChar[] = {
1354 			"<NUL>", "<SOH>", "<STX>", "<ETX>",
1355 			"<EOT>", "<ENQ>", "<ACK>", "<BEL>",
1356 			"<BS>" , "<HT>" , "<LF>" , "<VT>" ,
1357 			"<FF>" , "<CR>" , "<SO>" , "<SI>" ,
1358 			"<DLE>", "<DC1>", "<DC2>", "<DC3>",
1359 			"<DC4>", "<NAK>", "<SYN>", "<ETB>",
1360 			"<CAN>", "<EM>" , "<SUB>", "<ESC>",
1361 			"<FS>" , "<GS>" , "<RS>" , "<US>" ,
1362 			" " } ;
1363 
1364 	int	i, j, n ;
1365 
1366 	for ( i = j = 0 ; i < iInputLen && j < iOutputLen ; i ++ ) {
1367 		if ( isprint( (int)sInput[i] ) ) {
1368 			n = 1 ;
1369 			if ( j + 1 >= iOutputLen )
1370 				break ;
1371 			sOutput[j] = sInput[i] ;
1372 		} else if ( ( sInput[i] & 0xFF ) <
1373 			    COUNTOF(printableControlChar) ) {
1374 			n = strlen( printableControlChar[sInput[i] & 0xFF] ) ;
1375 			if ( j + n + 1 >= iOutputLen )
1376 				break ;
1377 			strncpy( sOutput + j,
1378 				 printableControlChar[sInput[i] & 0xFF],
1379 				 (size_t)iOutputLen - j ) ;
1380 		} else {
1381 			n = 5 ;
1382 			if ( j + n + 1 >= iOutputLen ) break ;
1383 			snprintf( sOutput + j, (size_t)iOutputLen - j,
1384 				  "<x%X>", sInput[i] & 0xFF ) ;
1385 		}
1386 		j += n ;
1387 	}
1388 
1389 	sOutput[min(j, iOutputLen - 1)] = '\0' ;
1390 
1391 }
1392 
1393 /**************************************************************************************************/
1394 
1395 #else
1396 int refclock_jjy_bs ;
1397 #endif /* REFCLOCK */
1398