xref: /freebsd/contrib/ntp/ntpd/refclock_jjy.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*
2  * refclock_jjy - clock driver for JJY receivers
3  */
4 
5 /**********************************************************************/
6 /*                                                                    */
7 /*  Copyright (C) 2001, Takao Abe.  All rights reserved.              */
8 /*                                                                    */
9 /*  Permission to use, copy, modify, and distribute this software     */
10 /*  and its documentation for any purpose is hereby granted           */
11 /*  without fee, provided that the following conditions are met:      */
12 /*                                                                    */
13 /*  One retains the entire copyright notice properly, and both the    */
14 /*  copyright notice and this license. in the documentation and/or    */
15 /*  other materials provided with the distribution.                   */
16 /*                                                                    */
17 /*  This software and the name of the author must not be used to      */
18 /*  endorse or promote products derived from this software without    */
19 /*  prior written permission.                                         */
20 /*                                                                    */
21 /*  THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED    */
22 /*  WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE        */
23 /*  IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A          */
24 /*  PARTICULAR PURPOSE.                                               */
25 /*  IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT,  */
26 /*  INDIRECT, GENERAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES   */
27 /*  ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE        */
28 /*  GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS      */
29 /*  INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,     */
30 /*  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING        */
31 /*  NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF    */
32 /*  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
33 /*                                                                    */
34 /*  This driver is developed in my private time, and is opened as     */
35 /*  voluntary contributions for the NTP.                              */
36 /*  The manufacturer of the JJY receiver has not participated in      */
37 /*  a development of this driver.                                     */
38 /*  The manufacturer does not warrant anything about this driver,     */
39 /*  and is not liable for anything about this driver.                 */
40 /*                                                                    */
41 /**********************************************************************/
42 /*                                                                    */
43 /*  Author     Takao Abe                                              */
44 /*  Email      abetakao@bea.hi-ho.ne.jp                               */
45 /*  Homepage   http://www.bea.hi-ho.ne.jp/abetakao/                   */
46 /*                                                                    */
47 /**********************************************************************/
48 /*                                                                    */
49 /*  History                                                           */
50 /*                                                                    */
51 /*  2001/07/15                                                        */
52 /*    [New]    Support the Tristate Ltd. JJY receiver                 */
53 /*                                                                    */
54 /*  2001/08/04                                                        */
55 /*    [Change] Log to clockstats even if bad reply                    */
56 /*    [Fix]    PRECISION = (-3) (about 100 ms)                        */
57 /*    [Add]    Support the C-DEX Co.Ltd. JJY receiver                 */
58 /*  2001/12/04                                                        */
59 /*    [Fix]    C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp )      */
60 /*                                                                    */
61 /**********************************************************************/
62 
63 #ifdef HAVE_CONFIG_H
64 #include <config.h>
65 #endif
66 
67 #if defined(REFCLOCK) && defined(CLOCK_JJY)
68 
69 #include <stdio.h>
70 #include <ctype.h>
71 #include <string.h>
72 #include <sys/time.h>
73 #include <time.h>
74 
75 #include "ntpd.h"
76 #include "ntp_io.h"
77 #include "ntp_tty.h"
78 #include "ntp_refclock.h"
79 #include "ntp_calendar.h"
80 #include "ntp_stdlib.h"
81 
82 /**********************************************************************/
83 /*                                                                    */
84 /*  The Tristate Ltd. JJY receiver JJY01                              */
85 /*                                                                    */
86 /*  Command        Response                 Remarks                   */
87 /*  ------------   ----------------------   ---------------------     */
88 /*  date<CR><LF>   YYYY/MM/DD XXX<CR><LF>                             */
89 /*  time<CR><LF>   HH:MM:SS<CR><LF>                                   */
90 /*  stim<CR><LF>   HH:MM:SS<CR><LF>         Reply at just second      */
91 /*                                                                    */
92 /*  During synchronization after a receiver is turned on,             */
93 /*  It replies the past time from 2000/01/01 00:00:00.                */
94 /*  The function "refclock_process" checks the time and tells         */
95 /*  as an insanity time.                                              */
96 /*                                                                    */
97 /**********************************************************************/
98 /*                                                                    */
99 /*  The C-DEX Co. Ltd. JJY receiver JST2000                           */
100 /*                                                                    */
101 /*  Command        Response                 Remarks                   */
102 /*  ------------   ----------------------   ---------------------     */
103 /*  <ENQ>1J<ETX>   <STX>JYYMMDD HHMMSSS<ETX>                          */
104 /*                                                                    */
105 /**********************************************************************/
106 
107 /*
108  * Interface definitions
109  */
110 #define	DEVICE  	"/dev/jjy%d"    /* device name and unit */
111 #define	SPEED232	B9600           /* uart speed (9600 baud) */
112 #define	REFID   	"JJY"           /* reference ID */
113 #define	DESCRIPTION	"JJY Receiver"
114 #define	PRECISION	(-3)           /* precision assumed (about 100 ms) */
115 
116 /*
117  * JJY unit control structure
118  */
119 struct jjyunit {
120 	char	unittype ;	/* UNITTYPE_XXXXXXXXXX */
121 	short	version ;
122 	short	linediscipline ;	/* LDISC_CLK or LDISC_RAW */
123 	int 	linecount ;
124 	int 	lineerror ;
125 	int 	year, month, day, hour, minute, second, msecond ;
126 /* LDISC_RAW only */
127 #define	MAX_LINECOUNT	8
128 #define	MAX_RAWBUF   	64
129 	int 	lineexpect ;
130 	int 	charexpect [ MAX_LINECOUNT ] ;
131 	int 	charcount ;
132 	char	rawbuf [ MAX_RAWBUF ] ;
133 };
134 
135 #define	UNITTYPE_TRISTATE_JJY01	1
136 #define	UNITTYPE_CDEX_JST2000  	2
137 
138 /*
139  * Function prototypes
140  */
141 static	int 	jjy_start                   P((int, struct peer *));
142 static	void	jjy_shutdown                P((int, struct peer *));
143 static	void	jjy_poll                    P((int, struct peer *));
144 static	void	jjy_poll_tristate_jjy01     P((int, struct peer *));
145 static	void	jjy_poll_cdex_jst2000       P((int, struct peer *));
146 static	void	jjy_receive                 P((struct recvbuf *));
147 static	int 	jjy_receive_tristate_jjy01  P((struct recvbuf *));
148 static	int 	jjy_receive_cdex_jst2000    P((struct recvbuf *));
149 
150 /*
151  * Transfer vector
152  */
153 struct	refclock refclock_jjy = {
154 	jjy_start,      /* start up driver */
155 	jjy_shutdown,   /* shutdown driver */
156 	jjy_poll,       /* transmit poll message */
157 	noentry,        /* not used */
158 	noentry,        /* not used */
159 	noentry,        /* not used */
160 	NOFLAGS         /* not used */
161 };
162 
163 /*
164  * Start up driver return code
165  */
166 #define	RC_START_SUCCESS	1
167 #define	RC_START_ERROR  	0
168 
169 /*
170  * Local constants definition
171  */
172 
173 #define	MAX_LOGTEXT	64
174 
175 
176 /**************************************************************************************************/
177 /*  jjy_start - open the devices and initialize data for processing                               */
178 /**************************************************************************************************/
179 static int
180 jjy_start ( int unit, struct peer *peer )
181 {
182 
183 	struct jjyunit      *up ;
184 	struct refclockproc *pp ;
185 	int 	fd ;
186 	char	*pDeviceName ;
187 	short	iDiscipline ;
188 
189 #ifdef DEBUG
190 	if ( debug ) {
191 		printf ( "jjy_start (refclock_jjy.c) : %s  mode=%d  ", ntoa(&peer->srcadr), peer->ttl ) ;
192 		printf ( DEVICE, unit ) ;
193 		printf ( "\n" ) ;
194 	}
195 #endif
196 	/*
197 	 * Open serial port
198 	 */
199 	if ( ! ( pDeviceName = (char*) emalloc ( strlen(DEVICE) + 10 ) ) ) {
200 		return RC_START_ERROR ;
201 	}
202 	sprintf ( pDeviceName, DEVICE, unit ) ;
203 
204 	/*
205 	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
206 	 */
207 	switch ( peer->ttl ) {
208 	case 0 :
209 	case 1 : iDiscipline = LDISC_CLK ; break ;
210 	case 2 : iDiscipline = LDISC_RAW ; break ;
211 	default :
212 		msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
213 		          ntoa(&peer->srcadr), peer->ttl ) ;
214 		free ( (void*) pDeviceName ) ;
215 		return RC_START_ERROR ;
216 	}
217 
218 	if ( ! ( fd = refclock_open ( pDeviceName, SPEED232, iDiscipline ) ) ) {
219 		free ( (void*) pDeviceName ) ;
220 		return RC_START_ERROR ;
221 	}
222 	free ( (void*) pDeviceName ) ;
223 
224 	/*
225 	 * Allocate and initialize unit structure
226 	 */
227 	if ( ! ( up = (struct jjyunit *) emalloc (sizeof(struct jjyunit)) ) ) {
228 		close ( fd ) ;
229 		return RC_START_ERROR ;
230 	}
231 
232 	memset ( (char*)up, 0, sizeof(struct jjyunit) ) ;
233 	up->linediscipline = iDiscipline ;
234 
235 	/*
236 	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
237 	 */
238 	switch ( peer->ttl ) {
239 	case 0 :
240 		/*
241 		 * The mode 0 is a default clock type at this time.
242 		 * But this will be change to auto-detect mode in the future.
243 		 */
244 	case 1 :
245 		up->unittype = UNITTYPE_TRISTATE_JJY01 ;
246 		up->version  = 100 ;
247 		up->lineexpect = 2 ;
248 		up->charexpect[0] = 14 ; /* YYYY/MM/DD WWW<CR><LF> */
249 		up->charexpect[1] =  8 ; /* HH:MM:SS<CR><LF> */
250 		break ;
251 	case 2 :
252 		up->unittype = UNITTYPE_CDEX_JST2000 ;
253 		up->lineexpect = 1 ;
254 		up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
255 		break ;
256 	default :
257 		msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
258 		          ntoa(&peer->srcadr), peer->ttl ) ;
259 		close ( fd ) ;
260 		free ( (void*) up ) ;
261 		return RC_START_ERROR ;
262 	}
263 
264 	pp = peer->procptr ;
265 	pp->unitptr       = (caddr_t) up ;
266 	pp->io.clock_recv = jjy_receive ;
267 	pp->io.srcclock   = (caddr_t) peer ;
268 	pp->io.datalen    = 0 ;
269 	pp->io.fd         = fd ;
270 	if ( ! io_addclock(&pp->io) ) {
271 		close ( fd ) ;
272 		free ( (void*) up ) ;
273 		return RC_START_ERROR ;
274 	}
275 
276 	/*
277 	 * Initialize miscellaneous variables
278 	 */
279 	peer->precision = PRECISION ;
280 	peer->burst     = 1 ;
281 	pp->clockdesc   = DESCRIPTION ;
282 	memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
283 
284 	return RC_START_SUCCESS ;
285 
286 }
287 
288 
289 /**************************************************************************************************/
290 /*  jjy_shutdown - shutdown the clock                                                             */
291 /**************************************************************************************************/
292 static void
293 jjy_shutdown ( int unit, struct peer *peer )
294 {
295 
296 	struct jjyunit      *up;
297 	struct refclockproc *pp;
298 
299 	pp = peer->procptr ;
300 	up = (struct jjyunit *) pp->unitptr ;
301 	io_closeclock ( &pp->io ) ;
302 	free ( (void*) up ) ;
303 
304 }
305 
306 
307 /**************************************************************************************************/
308 /*  jjy_receive - receive data from the serial interface                                          */
309 /**************************************************************************************************/
310 static void
311 jjy_receive ( struct recvbuf *rbufp )
312 {
313 
314 	struct jjyunit      *up ;
315 	struct refclockproc *pp ;
316 	struct peer         *peer;
317 
318 	l_fp	tRecvTimestamp;		/* arrival timestamp */
319 	int 	rc ;
320 	char	sLogText [ MAX_LOGTEXT ] ;
321 	int 	i, bCntrlChar ;
322 
323 	/*
324 	 * Initialize pointers and read the timecode and timestamp
325 	 */
326 	peer = (struct peer *) rbufp->recv_srcclock ;
327 	pp = peer->procptr ;
328 	up = (struct jjyunit *) pp->unitptr ;
329 
330 	/*
331 	 * Get next input line
332 	 */
333 	pp->lencode  = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
334 
335 	if ( up->linediscipline == LDISC_RAW ) {
336 		/*
337 		 * The reply with <STX> and <ETX> may give a blank line
338 		 */
339 		if ( pp->lencode == 0  &&  up->charcount == 0 ) return ;
340 		/*
341 		 * Copy received charaters to temporary buffer
342 		 */
343 		for ( i = 0 ; i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ; i ++ , up->charcount ++ ) {
344 			up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
345 		}
346 		while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
347 			for ( i = 0 ; i < up->charcount - 1 ; i ++ ) up->rawbuf[i] = up->rawbuf[i+1] ;
348 			up->charcount -- ;
349 		}
350 		bCntrlChar = 0 ;
351 		for ( i = 0 ; i < up->charcount ; i ++ ) {
352 			if ( up->rawbuf[i] < ' ' ) {
353 				bCntrlChar = 1 ;
354 				break ;
355 			}
356 		}
357 		if ( pp->lencode > 0  &&  up->linecount < up->lineexpect ) {
358 			if ( bCntrlChar == 0  &&  up->charcount < up->charexpect[up->linecount] ) return ;
359 		}
360 		up->rawbuf[up->charcount] = 0 ;
361 	} else {
362 		/*
363 		 * The reply with <CR><LF> gives a blank line
364 		 */
365 		if ( pp->lencode == 0 ) return ;
366 	}
367 	/*
368 	 * We get down to business
369 	 */
370 
371 	pp->lastrec = tRecvTimestamp ;
372 
373 	up->linecount ++ ;
374 
375 	if ( up->lineerror != 0 ) return ;
376 
377 	switch ( up->unittype ) {
378 
379 	case UNITTYPE_TRISTATE_JJY01 :
380 		rc = jjy_receive_tristate_jjy01  ( rbufp ) ;
381 		break ;
382 
383 	case UNITTYPE_CDEX_JST2000 :
384 		rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
385 		break ;
386 
387 	default :
388 		rc = 0 ;
389 		break ;
390 
391 	}
392 
393 	if ( up->linediscipline == LDISC_RAW ) {
394 		if ( up->linecount <= up->lineexpect  &&  up->charcount > up->charexpect[up->linecount-1] ) {
395 			for ( i = 0 ; i < up->charcount - up->charexpect[up->linecount-1] ; i ++ ) {
396 				up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
397 			}
398 			up->charcount -= up->charexpect[up->linecount-1] ;
399 		} else {
400 			up->charcount = 0 ;
401 		}
402 	}
403 
404 	if ( rc == 0 ) return ;
405 
406 	if ( up->lineerror != 0 ) {
407 		refclock_report ( peer, CEVNT_BADREPLY ) ;
408 		strcpy  ( sLogText, "BAD REPLY [" ) ;
409 		if ( up->linediscipline == LDISC_RAW ) {
410 			strncat ( sLogText, up->rawbuf, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
411 		} else {
412 			strncat ( sLogText, pp->a_lastcode, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
413 		}
414 		sLogText[MAX_LOGTEXT-1] = 0 ;
415 		if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 ) strcat ( sLogText, "]" ) ;
416 		record_clock_stats ( &peer->srcadr, sLogText ) ;
417 		return ;
418 	}
419 
420 	pp->year   = up->year ;
421 	pp->day    = ymd2yd ( up->year, up->month, up->day ) ;
422 	pp->hour   = up->hour ;
423 	pp->minute = up->minute ;
424 	pp->second = up->second ;
425 	pp->nsec   = up->msecond * 1000000;
426 
427 	/*
428 	 * JST to UTC
429 	 */
430 	pp->hour -= 9 ;
431 	if ( pp->hour < 0 ) {
432 		pp->hour += 24 ;
433 		pp->day -- ;
434 		if ( pp->day < 1 ) {
435 			pp->year -- ;
436 			pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
437 		}
438 	}
439 #ifdef DEBUG
440 	if ( debug ) {
441 		printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d JST   ",
442 		          up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
443 		printf ( "( %04d/%03d %02d:%02d:%02d UTC )\n",
444 		          pp->year, pp->day, pp->hour, pp->minute, pp->second ) ;
445 	}
446 #endif
447 
448 	/*
449 	 * Process the new sample in the median filter and determine the
450 	 * timecode timestamp.
451 	 */
452 	if ( ! refclock_process ( pp ) ) {
453 		refclock_report(peer, CEVNT_BADTIME);
454 		sprintf ( sLogText, "BAD TIME %04d/%02d/%02d %02d:%02d:%02d JST",
455 		          up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
456 		record_clock_stats ( &peer->srcadr, sLogText ) ;
457 		return ;
458 	}
459 
460 	sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d JST",
461 	          up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
462 	pp->lastref = pp->lastrec;
463 	refclock_receive(peer);
464 	record_clock_stats ( &peer->srcadr, sLogText ) ;
465 }
466 
467 /**************************************************************************************************/
468 
469 static int
470 jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
471 {
472 
473 	struct jjyunit      *up ;
474 	struct refclockproc *pp ;
475 	struct peer         *peer;
476 
477 	char	*pBuf ;
478 	int 	iLen ;
479 	int 	rc ;
480 
481 	/*
482 	 * Initialize pointers and read the timecode and timestamp
483 	 */
484 	peer = (struct peer *) rbufp->recv_srcclock ;
485 	pp = peer->procptr ;
486 	up = (struct jjyunit *) pp->unitptr ;
487 
488 	if ( up->linediscipline == LDISC_RAW ) {
489 		pBuf = up->rawbuf ;
490 		iLen = up->charcount ;
491 	} else {
492 	    pBuf = pp->a_lastcode ;
493 	    iLen = pp->lencode ;
494 	}
495 
496 	switch ( up->linecount ) {
497 
498 	case 1 : /* YYYY/MM/DD */
499 
500 		if ( iLen < 10 ) {
501 			up->lineerror = 1 ;
502 			break ;
503 		}
504 		rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
505 		if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
506 			up->lineerror = 1 ;
507 			break ;
508 		}
509 		return 0 ;
510 
511 	case 2 : /* HH:MM:SS */
512 
513 		if ( iLen < 8 ) {
514 			up->lineerror = 1 ;
515 			break ;
516 		}
517 		rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
518 		if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
519 			up->lineerror = 1 ;
520 			break ;
521 		}
522 		up->msecond = 0 ;
523 		if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
524 			/*
525 			 * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
526 			 * But the JJY receiver replies a date and time separately.
527 			 * Just after midnight transtions, we ignore this time.
528 			 */
529 			return 0 ;
530 		}
531 		break ;
532 
533 	default : /*  Unexpected reply */
534 
535 		up->lineerror = 1 ;
536 		break ;
537 
538 	}
539 
540 	return 1 ;
541 
542 }
543 
544 /**************************************************************************************************/
545 
546 static int
547 jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
548 {
549 
550 	struct jjyunit      *up ;
551 	struct refclockproc *pp ;
552 	struct peer         *peer;
553 
554 	char	*pBuf ;
555 	int 	iLen ;
556 	int 	rc ;
557 
558 	/*
559 	 * Initialize pointers and read the timecode and timestamp
560 	 */
561 	peer = (struct peer *) rbufp->recv_srcclock ;
562 	pp = peer->procptr ;
563 	up = (struct jjyunit *) pp->unitptr ;
564 
565 	if ( up->linediscipline == LDISC_RAW ) {
566 		pBuf = up->rawbuf ;
567 		iLen = up->charcount ;
568 	} else {
569 	    pBuf = pp->a_lastcode ;
570 	    iLen = pp->lencode ;
571 	}
572 
573 	switch ( up->linecount ) {
574 
575 	case 1 : /* JYYMMDD HHMMSSS */
576 
577 		if ( iLen < 15 ) {
578 			up->lineerror = 1 ;
579 			break ;
580 		}
581 		rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
582 		              &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
583 		if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
584 		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
585 			up->lineerror = 1 ;
586 			break ;
587 		}
588 		up->year    += 2000 ;
589 		up->msecond *= 100 ;
590 		break ;
591 
592 	default : /*  Unexpected reply */
593 
594 		up->lineerror = 1 ;
595 		break ;
596 
597 	}
598 
599 	return 1 ;
600 
601 }
602 
603 /**************************************************************************************************/
604 /*  jjy_poll - called by the transmit procedure                                                   */
605 /**************************************************************************************************/
606 static void
607 jjy_poll ( int unit, struct peer *peer )
608 {
609 
610 	struct jjyunit      *up;
611 	struct refclockproc *pp;
612 
613 	pp = peer->procptr;
614 	up = (struct jjyunit *) pp->unitptr ;
615 
616 	if ( pp->polls > 0  &&  up->linecount == 0 ) {
617 		/*
618 		 * No reply for last command
619 		 */
620 		refclock_report ( peer, CEVNT_TIMEOUT ) ;
621 	}
622 
623 #ifdef DEBUG
624 	if ( debug ) {
625 		printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
626 	}
627 #endif
628 
629 	pp->polls ++ ;
630 
631 	up->linecount = 0 ;
632 	up->lineerror = 0 ;
633 	up->charcount = 0 ;
634 
635 	switch ( up->unittype ) {
636 
637 	case UNITTYPE_TRISTATE_JJY01 :
638 		jjy_poll_tristate_jjy01  ( unit, peer ) ;
639 		break ;
640 
641 	case UNITTYPE_CDEX_JST2000 :
642 		jjy_poll_cdex_jst2000 ( unit, peer ) ;
643 		break ;
644 
645 	default :
646 		break ;
647 
648 	}
649 
650 }
651 
652 /**************************************************************************************************/
653 
654 static void
655 jjy_poll_tristate_jjy01  ( int unit, struct peer *peer )
656 {
657 
658 	struct jjyunit      *up;
659 	struct refclockproc *pp;
660 
661 	pp = peer->procptr;
662 	up = (struct jjyunit *) pp->unitptr ;
663 
664 	/*
665 	 * Send "date<CR><LF>" command
666 	 */
667 
668 	if ( write ( pp->io.fd, "date\r\n",6 ) != 6  ) {
669 		refclock_report ( peer, CEVNT_FAULT ) ;
670 	}
671 
672 	/*
673 	 * Send "stim<CR><LF>" or "time<CR><LF>" command
674 	 */
675 
676 	if ( up->version >= 100 ) {
677 		if ( write ( pp->io.fd, "stim\r\n",6 ) != 6  ) {
678 			refclock_report ( peer, CEVNT_FAULT ) ;
679 		}
680 	} else {
681 		if ( write ( pp->io.fd, "time\r\n",6 ) != 6  ) {
682 			refclock_report ( peer, CEVNT_FAULT ) ;
683 		}
684 	}
685 
686 }
687 
688 /**************************************************************************************************/
689 
690 static void
691 jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
692 {
693 
694 	struct refclockproc *pp;
695 
696 	pp = peer->procptr;
697 
698 	/*
699 	 * Send "<ENQ>1J<ETX>" command
700 	 */
701 
702 	if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4  ) {
703 		refclock_report ( peer, CEVNT_FAULT ) ;
704 	}
705 
706 }
707 
708 #else
709 int refclock_jjy_bs ;
710 #endif /* REFCLOCK */
711