PageRenderTime 77ms CodeModel.GetById 14ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/ntpd/refclock_jjy.c

https://bitbucket.org/freebsd/freebsd-head/
C | 1159 lines | 716 code | 188 blank | 255 comment | 191 complexity | 9a7c3f416ad5bc1c0de611b9ebcc6058 MD5 | raw file
   1/*
   2 * refclock_jjy - clock driver for JJY receivers
   3 */
   4
   5/**********************************************************************/
   6/*                                                                    */
   7/*  Copyright (C) 2001-2004, 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/*                                                                    */
  59/*  2001/12/04                                                        */
  60/*    [Fix]    C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp )      */
  61/*                                                                    */
  62/*  2002/07/12                                                        */
  63/*    [Fix]    Portability for FreeBSD ( patched by the user )        */
  64/*                                                                    */
  65/*  2004/10/31                                                        */
  66/*    [Change] Command send timing for the Tristate Ltd. JJY receiver */
  67/*             JJY-01 ( Firmware version 2.01 )                       */
  68/*             Thanks to Andy Taki for testing under FreeBSD          */
  69/*                                                                    */
  70/*  2004/11/28                                                        */
  71/*    [Add]    Support the Echo Keisokuki LT-2000 receiver            */
  72/*                                                                    */
  73/*  2006/11/04                                                        */
  74/*    [Fix]    C-DEX JST2000                                          */
  75/*             Thanks to Hideo Kuramatsu for the patch                */
  76/*                                                                    */
  77/*  2009/04/05                                                        */
  78/*    [Add]    Support the CITIZEN T.I.C JJY-200 receiver             */
  79/*                                                                    */
  80/**********************************************************************/
  81
  82#ifdef HAVE_CONFIG_H
  83#include <config.h>
  84#endif
  85
  86#if defined(REFCLOCK) && defined(CLOCK_JJY)
  87
  88#include <stdio.h>
  89#include <ctype.h>
  90#include <string.h>
  91#include <sys/time.h>
  92#include <time.h>
  93
  94#include "ntpd.h"
  95#include "ntp_io.h"
  96#include "ntp_tty.h"
  97#include "ntp_refclock.h"
  98#include "ntp_calendar.h"
  99#include "ntp_stdlib.h"
 100
 101/**********************************************************************/
 102/*                                                                    */
 103/*  The Tristate Ltd. JJY receiver JJY01                              */
 104/*                                                                    */
 105/*  Command        Response                 Remarks                   */
 106/*  ------------   ----------------------   ---------------------     */
 107/*  date<CR><LF>   YYYY/MM/DD XXX<CR><LF>                             */
 108/*  time<CR><LF>   HH:MM:SS<CR><LF>                                   */
 109/*  stim<CR><LF>   HH:MM:SS<CR><LF>         Reply at just second      */
 110/*                                                                    */
 111/*  During synchronization after a receiver is turned on,             */
 112/*  It replies the past time from 2000/01/01 00:00:00.                */
 113/*  The function "refclock_process" checks the time and tells         */
 114/*  as an insanity time.                                              */
 115/*                                                                    */
 116/**********************************************************************/
 117/*                                                                    */
 118/*  The C-DEX Co. Ltd. JJY receiver JST2000                           */
 119/*                                                                    */
 120/*  Command        Response                 Remarks                   */
 121/*  ------------   ----------------------   ---------------------     */
 122/*  <ENQ>1J<ETX>   <STX>JYYMMDD HHMMSSS<ETX>                          */
 123/*                                                                    */
 124/**********************************************************************/
 125/*                                                                    */
 126/*  The Echo Keisokuki Co. Ltd. JJY receiver LT2000                   */
 127/*                                                                    */
 128/*  Command        Response                 Remarks                   */
 129/*  ------------   ----------------------   ---------------------     */
 130/*  #                                       Mode 1 (Request&Send)     */
 131/*  T              YYMMDDWHHMMSS<BCC1><BCC2><CR>                      */
 132/*  C                                       Mode 2 (Continuous)       */
 133/*                 YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR>              */
 134/*                 <SUB>                    Second signal             */
 135/*                                                                    */
 136/**********************************************************************/
 137/*                                                                    */
 138/*  The CITIZEN T.I.C CO., LTD. JJY receiver JJY200                   */
 139/*                                                                    */
 140/*  Command        Response                 Remarks                   */
 141/*  ------------   ----------------------   ---------------------     */
 142/*                 'XX YY/MM/DD W HH:MM:SS<CR>                        */
 143/*                                          XX: OK|NG|ER              */
 144/*                                          W:  0(Monday)-6(Sunday)   */
 145/*                                                                    */
 146/**********************************************************************/
 147
 148/*
 149 * Interface definitions
 150 */
 151#define	DEVICE  	"/dev/jjy%d"    /* device name and unit */
 152#define	SPEED232	B9600           /* uart speed (9600 baud) */
 153#define	SPEED232_TRISTATE_JJY01         B9600   /* UART speed (9600 baud) */
 154#define	SPEED232_CDEX_JST2000           B9600   /* UART speed (9600 baud) */
 155#define	SPEED232_ECHOKEISOKUKI_LT2000   B9600   /* UART speed (9600 baud) */
 156#define	SPEED232_CITIZENTIC_JJY200      B4800   /* UART speed (4800 baud) */
 157#define	REFID   	"JJY"           /* reference ID */
 158#define	DESCRIPTION	"JJY Receiver"
 159#define	PRECISION	(-3)           /* precision assumed (about 100 ms) */
 160
 161/*
 162 * JJY unit control structure
 163 */
 164struct jjyunit {
 165	char	unittype ;          /* UNITTYPE_XXXXXXXXXX */
 166    short   operationmode ;     /* Echo Keisokuki LT-2000 : 1 or 2 */
 167	short	version ;
 168	short	linediscipline ;	/* LDISC_CLK or LDISC_RAW */
 169    char    bPollFlag ;         /* Set by jjy_pool and Reset by jjy_receive */
 170	int 	linecount ;
 171	int 	lineerror ;
 172	int 	year, month, day, hour, minute, second, msecond ;
 173/* LDISC_RAW only */
 174#define	MAX_LINECOUNT	8
 175#define	MAX_RAWBUF   	64
 176	int 	lineexpect ;
 177	int 	charexpect [ MAX_LINECOUNT ] ;
 178	int 	charcount ;
 179	char	rawbuf [ MAX_RAWBUF ] ;
 180};
 181
 182#define	UNITTYPE_TRISTATE_JJY01	1
 183#define	UNITTYPE_CDEX_JST2000  	2
 184#define	UNITTYPE_ECHOKEISOKUKI_LT2000  	3
 185#define	UNITTYPE_CITIZENTIC_JJY200  	4
 186
 187/*
 188 * Function prototypes
 189 */
 190static	int 	jjy_start                   P((int, struct peer *));
 191static	void	jjy_shutdown                P((int, struct peer *));
 192static	void	jjy_poll                    P((int, struct peer *));
 193static	void	jjy_poll_tristate_jjy01     P((int, struct peer *));
 194static	void	jjy_poll_cdex_jst2000       P((int, struct peer *));
 195static	void	jjy_poll_echokeisokuki_lt2000    P((int, struct peer *));
 196static  void    jjy_poll_citizentic_jjy200          P((int, struct peer *));
 197static	void	jjy_receive                 P((struct recvbuf *));
 198static	int 	jjy_receive_tristate_jjy01  P((struct recvbuf *));
 199static	int 	jjy_receive_cdex_jst2000    P((struct recvbuf *));
 200static	int 	jjy_receive_echokeisokuki_lt2000 P((struct recvbuf *));
 201static  int     jjy_receive_citizentic_jjy200       P((struct recvbuf *));
 202
 203/*
 204 * Transfer vector
 205 */
 206struct	refclock refclock_jjy = {
 207	jjy_start,      /* start up driver */
 208	jjy_shutdown,   /* shutdown driver */
 209	jjy_poll,       /* transmit poll message */
 210	noentry,        /* not used */
 211	noentry,        /* not used */
 212	noentry,        /* not used */
 213	NOFLAGS         /* not used */
 214};
 215
 216/*
 217 * Start up driver return code
 218 */
 219#define	RC_START_SUCCESS	1
 220#define	RC_START_ERROR  	0
 221
 222/*
 223 * Local constants definition
 224 */
 225
 226#define	MAX_LOGTEXT	64
 227
 228
 229/**************************************************************************************************/
 230/*  jjy_start - open the devices and initialize data for processing                               */
 231/**************************************************************************************************/
 232static int
 233jjy_start ( int unit, struct peer *peer )
 234{
 235
 236	struct jjyunit      *up ;
 237	struct refclockproc *pp ;
 238	int 	fd ;
 239	char	*pDeviceName ;
 240	short	iDiscipline ;
 241	int 	iSpeed232 ;
 242
 243#ifdef DEBUG
 244	if ( debug ) {
 245		printf ( "jjy_start (refclock_jjy.c) : %s  mode=%d  ", ntoa(&peer->srcadr), peer->ttl ) ;
 246		printf ( DEVICE, unit ) ;
 247		printf ( "\n" ) ;
 248	}
 249#endif
 250	/*
 251	 * Open serial port
 252	 */
 253	if ( ! ( pDeviceName = (char*) emalloc ( strlen(DEVICE) + 10 ) ) ) {
 254		return RC_START_ERROR ;
 255	}
 256	sprintf ( pDeviceName, DEVICE, unit ) ;
 257
 258	/*
 259	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
 260	 */
 261	switch ( peer->ttl ) {
 262	case 0 :
 263    case 1 :
 264        iDiscipline = LDISC_CLK ;
 265        iSpeed232   = SPEED232_TRISTATE_JJY01 ;
 266        break ;
 267    case 2 :
 268        iDiscipline = LDISC_RAW ;
 269        iSpeed232   = SPEED232_CDEX_JST2000   ;
 270        break ;
 271    case 3 :
 272        iDiscipline = LDISC_CLK ;
 273        iSpeed232   = SPEED232_ECHOKEISOKUKI_LT2000 ;
 274        break ;
 275    case 4 :
 276        iDiscipline = LDISC_CLK ;
 277        iSpeed232   = SPEED232_CITIZENTIC_JJY200 ;
 278        break ;
 279	default :
 280		msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
 281		          ntoa(&peer->srcadr), peer->ttl ) ;
 282		free ( (void*) pDeviceName ) ;
 283		return RC_START_ERROR ;
 284	}
 285
 286	if ( ! ( fd = refclock_open ( pDeviceName, iSpeed232, iDiscipline ) ) ) {
 287		free ( (void*) pDeviceName ) ;
 288		return RC_START_ERROR ;
 289	}
 290	free ( (void*) pDeviceName ) ;
 291
 292	/*
 293	 * Allocate and initialize unit structure
 294	 */
 295	if ( ! ( up = (struct jjyunit *) emalloc (sizeof(struct jjyunit)) ) ) {
 296		close ( fd ) ;
 297		return RC_START_ERROR ;
 298	}
 299
 300	memset ( (char*)up, 0, sizeof(struct jjyunit) ) ;
 301	up->linediscipline = iDiscipline ;
 302
 303	/*
 304	 * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
 305	 */
 306	switch ( peer->ttl ) {
 307	case 0 :
 308		/*
 309		 * The mode 0 is a default clock type at this time.
 310		 * But this will be change to auto-detect mode in the future.
 311		 */
 312	case 1 :
 313		up->unittype = UNITTYPE_TRISTATE_JJY01 ;
 314		up->version  = 100 ;
 315		up->lineexpect = 2 ;
 316		up->charexpect[0] = 14 ; /* YYYY/MM/DD WWW<CR><LF> */
 317		up->charexpect[1] =  8 ; /* HH:MM:SS<CR><LF> */
 318		break ;
 319	case 2 :
 320		up->unittype = UNITTYPE_CDEX_JST2000 ;
 321		up->lineexpect = 1 ;
 322		up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
 323		break ;
 324	case 3 :
 325		up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
 326		up->operationmode = 2 ;  /* Mode 2 : Continuous mode */
 327		up->lineexpect = 1 ;
 328        switch ( up->operationmode ) {
 329        case 1 :
 330			up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
 331			break ;
 332		case 2 :
 333			up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
 334			break ;
 335		}
 336		break ;
 337    case 4 :
 338        up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
 339        up->lineexpect = 1 ;
 340        up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
 341        break ;
 342	default :
 343		msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
 344		          ntoa(&peer->srcadr), peer->ttl ) ;
 345		close ( fd ) ;
 346		free ( (void*) up ) ;
 347		return RC_START_ERROR ;
 348	}
 349
 350	pp = peer->procptr ;
 351	pp->unitptr       = (caddr_t) up ;
 352	pp->io.clock_recv = jjy_receive ;
 353	pp->io.srcclock   = (caddr_t) peer ;
 354	pp->io.datalen    = 0 ;
 355	pp->io.fd         = fd ;
 356	if ( ! io_addclock(&pp->io) ) {
 357		close ( fd ) ;
 358		free ( (void*) up ) ;
 359		return RC_START_ERROR ;
 360	}
 361
 362	/*
 363	 * Initialize miscellaneous variables
 364	 */
 365	peer->precision = PRECISION ;
 366	peer->burst     = 1 ;
 367	pp->clockdesc   = DESCRIPTION ;
 368	memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
 369
 370	return RC_START_SUCCESS ;
 371
 372}
 373
 374
 375/**************************************************************************************************/
 376/*  jjy_shutdown - shutdown the clock                                                             */
 377/**************************************************************************************************/
 378static void
 379jjy_shutdown ( int unit, struct peer *peer )
 380{
 381
 382	struct jjyunit      *up;
 383	struct refclockproc *pp;
 384
 385	pp = peer->procptr ;
 386	up = (struct jjyunit *) pp->unitptr ;
 387	io_closeclock ( &pp->io ) ;
 388	free ( (void*) up ) ;
 389
 390}
 391
 392
 393/**************************************************************************************************/
 394/*  jjy_receive - receive data from the serial interface                                          */
 395/**************************************************************************************************/
 396static void
 397jjy_receive ( struct recvbuf *rbufp )
 398{
 399
 400	struct jjyunit      *up ;
 401	struct refclockproc *pp ;
 402	struct peer         *peer;
 403
 404	l_fp	tRecvTimestamp;		/* arrival timestamp */
 405	int 	rc ;
 406	char	sLogText [ MAX_LOGTEXT ] ;
 407	int 	i, bCntrlChar ;
 408
 409	/*
 410	 * Initialize pointers and read the timecode and timestamp
 411	 */
 412	peer = (struct peer *) rbufp->recv_srcclock ;
 413	pp = peer->procptr ;
 414	up = (struct jjyunit *) pp->unitptr ;
 415
 416	/*
 417	 * Get next input line
 418	 */
 419	pp->lencode  = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
 420
 421	if ( up->linediscipline == LDISC_RAW ) {
 422		/*
 423		 * The reply with <STX> and <ETX> may give a blank line
 424		 */
 425		if ( pp->lencode == 0  &&  up->charcount == 0 ) return ;
 426		/*
 427		 * Copy received charaters to temporary buffer 
 428		 */
 429		for ( i = 0 ; i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ; i ++ , up->charcount ++ ) {
 430			up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
 431		}
 432		while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
 433			for ( i = 0 ; i < up->charcount - 1 ; i ++ ) up->rawbuf[i] = up->rawbuf[i+1] ;
 434			up->charcount -- ;
 435		}
 436		bCntrlChar = 0 ;
 437		for ( i = 0 ; i < up->charcount ; i ++ ) {
 438			if ( up->rawbuf[i] < ' ' ) {
 439				bCntrlChar = 1 ;
 440				break ;
 441			}
 442		}
 443		if ( pp->lencode > 0  &&  up->linecount < up->lineexpect ) {
 444			if ( bCntrlChar == 0  &&  up->charcount < up->charexpect[up->linecount] ) return ;
 445		}
 446		up->rawbuf[up->charcount] = 0 ;
 447	} else {
 448		/*
 449		 * The reply with <CR><LF> gives a blank line
 450		 */
 451		if ( pp->lencode == 0 ) return ;
 452	}
 453	/*
 454	 * We get down to business
 455	 */
 456
 457	pp->lastrec = tRecvTimestamp ;
 458
 459	up->linecount ++ ;
 460
 461	if ( up->lineerror != 0 ) return ;
 462
 463	switch ( up->unittype ) {
 464	
 465	case UNITTYPE_TRISTATE_JJY01 :
 466		rc = jjy_receive_tristate_jjy01  ( rbufp ) ;
 467		break ;
 468
 469	case UNITTYPE_CDEX_JST2000 :
 470		rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
 471		break ;
 472
 473	case UNITTYPE_ECHOKEISOKUKI_LT2000 :
 474		rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
 475		break ;
 476
 477    case UNITTYPE_CITIZENTIC_JJY200 :
 478        rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
 479        break ;
 480
 481	default :
 482		rc = 0 ;
 483		break ;
 484
 485	}
 486
 487	if ( up->linediscipline == LDISC_RAW ) {
 488		if ( up->linecount <= up->lineexpect  &&  up->charcount > up->charexpect[up->linecount-1] ) {
 489			for ( i = 0 ; i < up->charcount - up->charexpect[up->linecount-1] ; i ++ ) {
 490				up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
 491			}
 492			up->charcount -= up->charexpect[up->linecount-1] ;
 493		} else {
 494			up->charcount = 0 ;
 495		}
 496	}
 497
 498	if ( rc == 0 ) return ;
 499
 500    up->bPollFlag = 0 ;
 501
 502	if ( up->lineerror != 0 ) {
 503		refclock_report ( peer, CEVNT_BADREPLY ) ;
 504		strcpy  ( sLogText, "BAD REPLY [" ) ;
 505		if ( up->linediscipline == LDISC_RAW ) {
 506			strncat ( sLogText, up->rawbuf, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
 507		} else {
 508			strncat ( sLogText, pp->a_lastcode, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
 509		}
 510		sLogText[MAX_LOGTEXT-1] = 0 ;
 511		if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 ) strcat ( sLogText, "]" ) ;
 512		record_clock_stats ( &peer->srcadr, sLogText ) ;
 513		return ;
 514	}
 515
 516	pp->year   = up->year ;
 517	pp->day    = ymd2yd ( up->year, up->month, up->day ) ;
 518	pp->hour   = up->hour ;
 519	pp->minute = up->minute ;
 520	pp->second = up->second ;
 521	pp->nsec   = up->msecond * 1000000;
 522
 523	/* 
 524	 * JST to UTC 
 525	 */
 526	pp->hour -= 9 ;
 527	if ( pp->hour < 0 ) {
 528		pp->hour += 24 ;
 529		pp->day -- ;
 530		if ( pp->day < 1 ) {
 531			pp->year -- ;
 532			pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
 533		}
 534	}
 535#ifdef DEBUG
 536	if ( debug ) {
 537		printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST   ", 
 538		          up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
 539		printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
 540		          pp->year, pp->day, pp->hour, pp->minute, pp->second, (int)(pp->nsec/100000000) ) ;
 541	}
 542#endif
 543
 544	/*
 545	 * Process the new sample in the median filter and determine the
 546	 * timecode timestamp.
 547	 */
 548
 549	sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
 550	          up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
 551	record_clock_stats ( &peer->srcadr, sLogText ) ;
 552
 553	if ( ! refclock_process ( pp ) ) {
 554		refclock_report(peer, CEVNT_BADTIME);
 555		return ;
 556	}
 557
 558	pp->lastref = pp->lastrec;
 559	refclock_receive(peer);
 560
 561}
 562
 563/**************************************************************************************************/
 564
 565static int
 566jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
 567{
 568
 569	static	char	*sFunctionName = "jjy_receive_tristate_jjy01" ;
 570
 571	struct jjyunit      *up ;
 572	struct refclockproc *pp ;
 573	struct peer         *peer;
 574
 575	char	*pBuf ;
 576	int 	iLen ;
 577	int 	rc ;
 578
 579	/*
 580	 * Initialize pointers and read the timecode and timestamp
 581	 */
 582	peer = (struct peer *) rbufp->recv_srcclock ;
 583	pp = peer->procptr ;
 584	up = (struct jjyunit *) pp->unitptr ;
 585
 586	if ( up->linediscipline == LDISC_RAW ) {
 587		pBuf = up->rawbuf ;
 588		iLen = up->charcount ;
 589	} else {
 590	    pBuf = pp->a_lastcode ;
 591	    iLen = pp->lencode ;
 592	}
 593
 594	switch ( up->linecount ) {
 595
 596	case 1 : /* YYYY/MM/DD WWW */
 597
 598		if ( iLen != 14 ) {
 599#ifdef DEBUG
 600	        if ( debug >= 2 ) {
 601		        printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d  iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
 602	        }
 603#endif
 604			up->lineerror = 1 ;
 605			break ;
 606		}
 607		rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
 608		if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
 609#ifdef DEBUG
 610	        if ( debug >= 2 ) {
 611		        printf ( "%s (refclock_jjy.c) : Date error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
 612	        }
 613#endif
 614			up->lineerror = 1 ;
 615			break ;
 616		}
 617
 618		/*** Start of modification on 2004/10/31 */
 619		/*
 620		 * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
 621		 * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
 622		 * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
 623		 * so this driver issues the second command "stim" after the reply of the first command "date".
 624		 */
 625
 626		/*
 627		 * Send "stim<CR><LF>" or "time<CR><LF>" command
 628		 */
 629		 
 630
 631		if ( up->version >= 100 ) {
 632#ifdef DEBUG
 633			if ( debug ) {
 634				printf ( "%s (refclock_jjy.c) : send 'stim<CR><LF>'\n", sFunctionName ) ;
 635			}
 636#endif
 637			if ( write ( pp->io.fd, "stim\r\n",6 ) != 6  ) {
 638				refclock_report ( peer, CEVNT_FAULT ) ;
 639			}
 640		} else {
 641#ifdef DEBUG
 642			if ( debug ) {
 643				printf ( "%s (refclock_jjy.c) : send 'time<CR><LF>'\n", sFunctionName ) ;
 644			}
 645#endif
 646			if ( write ( pp->io.fd, "time\r\n",6 ) != 6  ) {
 647				refclock_report ( peer, CEVNT_FAULT ) ;
 648			}
 649		}
 650		/*** End of modification ***/
 651
 652		return 0 ;
 653
 654	case 2 : /* HH:MM:SS */
 655
 656		if ( iLen != 8 ) {
 657#ifdef DEBUG
 658	        if ( debug >= 2 ) {
 659		        printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d  iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
 660	        }
 661#endif
 662			up->lineerror = 1 ;
 663			break ;
 664		}
 665		rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
 666		if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
 667#ifdef DEBUG
 668	        if ( debug >= 2 ) {
 669		        printf ( "%s (refclock_jjy.c) : Time error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
 670	        }
 671#endif
 672			up->lineerror = 1 ;
 673			break ;
 674		}
 675		up->msecond = 0 ;
 676		if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
 677			/*
 678			 * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
 679			 * But the JJY receiver replies a date and time separately.
 680			 * Just after midnight transitions, we ignore this time.
 681			 */
 682			return 0 ;
 683		}
 684		break ;
 685
 686	default : /*  Unexpected reply */
 687
 688		up->lineerror = 1 ;
 689		break ;
 690
 691	}
 692
 693	return 1 ;
 694
 695}
 696
 697/**************************************************************************************************/
 698
 699static int
 700jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
 701{
 702
 703	static	char	*sFunctionName = "jjy_receive_cdex_jst2000" ;
 704
 705	struct jjyunit      *up ;
 706	struct refclockproc *pp ;
 707	struct peer         *peer;
 708
 709	char	*pBuf ;
 710	int 	iLen ;
 711	int 	rc ;
 712
 713	/*
 714	 * Initialize pointers and read the timecode and timestamp
 715	 */
 716	peer = (struct peer *) rbufp->recv_srcclock ;
 717	pp = peer->procptr ;
 718	up = (struct jjyunit *) pp->unitptr ;
 719
 720	if ( up->linediscipline == LDISC_RAW ) {
 721		pBuf = up->rawbuf ;
 722		iLen = up->charcount ;
 723	} else {
 724	    pBuf = pp->a_lastcode ;
 725	    iLen = pp->lencode ;
 726	}
 727
 728	switch ( up->linecount ) {
 729
 730	case 1 : /* JYYMMDD HHMMSSS */
 731
 732		if ( iLen != 15 ) {
 733#ifdef DEBUG
 734	        if ( debug >= 2 ) {
 735		        printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
 736	        }
 737#endif
 738			up->lineerror = 1 ;
 739			break ;
 740		}
 741		rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
 742		              &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
 743		if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
 744		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
 745#ifdef DEBUG
 746	        if ( debug >= 2 ) {
 747		        printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n", sFunctionName,
 748						 rc, up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond ) ;
 749	        }
 750#endif
 751			up->lineerror = 1 ;
 752			break ;
 753		}
 754		up->year    += 2000 ;
 755		up->msecond *= 100 ;
 756		break ;
 757
 758	default : /*  Unexpected reply */
 759
 760		up->lineerror = 1 ;
 761		break ;
 762
 763	}
 764
 765	return 1 ;
 766
 767}
 768
 769/**************************************************************************************************/
 770
 771static int
 772jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
 773{
 774
 775	static	char	*sFunctionName = "jjy_receive_echokeisokuki_lt2000" ;
 776
 777	struct jjyunit      *up ;
 778	struct refclockproc *pp ;
 779	struct peer         *peer;
 780
 781	char	*pBuf ;
 782	int 	iLen ;
 783	int 	rc ;
 784    int     i, ibcc, ibcc1, ibcc2 ;
 785
 786	/*
 787	 * Initialize pointers and read the timecode and timestamp
 788	 */
 789	peer = (struct peer *) rbufp->recv_srcclock ;
 790	pp = peer->procptr ;
 791	up = (struct jjyunit *) pp->unitptr ;
 792
 793	if ( up->linediscipline == LDISC_RAW ) {
 794		pBuf = up->rawbuf ;
 795		iLen = up->charcount ;
 796	} else {
 797	    pBuf = pp->a_lastcode ;
 798	    iLen = pp->lencode ;
 799	}
 800
 801	switch ( up->linecount ) {
 802
 803	case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
 804
 805		if ( ( up->operationmode == 1 && iLen != 15 ) || ( up->operationmode == 2 && iLen != 17 ) ) {
 806#ifdef DEBUG
 807	        if ( debug >= 2 ) {
 808		        printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
 809	        }
 810#endif
 811			if ( up->operationmode == 1 ) {
 812#ifdef DEBUG
 813				if ( debug ) {
 814					printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
 815				}
 816#endif
 817				if ( write ( pp->io.fd, "#",1 ) != 1  ) {
 818					refclock_report ( peer, CEVNT_FAULT ) ;
 819				}
 820			}
 821			up->lineerror = 1 ;
 822			break ;
 823		}
 824
 825		if ( up->operationmode == 1 ) {
 826
 827        	for ( i = ibcc = 0 ; i < 13 ; i ++ ) ibcc ^= pBuf[i] ;
 828        	ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
 829        	ibcc2 = 0x30 | ( ( ibcc      ) & 0xF ) ;
 830        	if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
 831#ifdef DEBUG
 832	        	if ( debug >= 2 ) {
 833		        	printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n", sFunctionName, pBuf[13]&0xFF, pBuf[14]&0xFF, ibcc1, ibcc2 ) ;
 834	        	}
 835#endif
 836				up->lineerror = 1 ;
 837				break ;
 838			}
 839
 840        }
 841
 842		rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
 843                      &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second ) ;
 844		if ( rc != 6 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
 845		  || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
 846#ifdef DEBUG
 847	        if ( debug >= 2 ) {
 848		        printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n", sFunctionName,
 849						 rc, up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
 850	        }
 851#endif
 852			up->lineerror = 1 ;
 853			break ;
 854		}
 855
 856		up->year += 2000 ;
 857
 858		if ( up->operationmode == 2 ) {
 859
 860			/* A time stamp comes on every 0.5 seccond in the mode 2 of the LT-2000. */
 861			up->msecond = 500 ;
 862			pp->second -- ;
 863			if ( pp->second < 0 ) {
 864				pp->second = 59 ;
 865				pp->minute -- ;
 866				if ( pp->minute < 0 ) {
 867					pp->minute = 59 ;
 868					pp->hour -- ;
 869					if ( pp->hour < 0 ) {
 870						pp->hour = 23 ;
 871						pp->day -- ;
 872						if ( pp->day < 1 ) {
 873							pp->year -- ;
 874							pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
 875						}
 876					}
 877				}
 878			}
 879
 880			/* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
 881#ifdef DEBUG
 882			if ( debug ) {
 883				printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
 884			}
 885#endif
 886			if ( write ( pp->io.fd, "#",1 ) != 1  ) {
 887				refclock_report ( peer, CEVNT_FAULT ) ;
 888			}
 889
 890		}
 891
 892		break ;
 893
 894	default : /*  Unexpected reply */
 895
 896#ifdef DEBUG
 897		if ( debug ) {
 898			printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
 899		}
 900#endif
 901		if ( write ( pp->io.fd, "#",1 ) != 1  ) {
 902			refclock_report ( peer, CEVNT_FAULT ) ;
 903		}
 904
 905		up->lineerror = 1 ;
 906		break ;
 907
 908	}
 909
 910	return 1 ;
 911
 912}
 913
 914/**************************************************************************************************/
 915
 916static int
 917jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
 918{
 919
 920    static  char    *sFunctionName = "jjy_receive_citizentic_jjy200" ;
 921
 922    struct jjyunit      *up ;
 923    struct refclockproc *pp ;
 924    struct peer         *peer;
 925
 926    char    *pBuf ;
 927    int     iLen ;
 928    int     rc ;
 929    char    cApostrophe, sStatus[3] ;
 930    int     iWeekday ;
 931
 932    /*
 933     * Initialize pointers and read the timecode and timestamp
 934     */
 935    peer = (struct peer *) rbufp->recv_srcclock ;
 936    pp = peer->procptr ;
 937    up = (struct jjyunit *) pp->unitptr ;
 938
 939    if ( up->linediscipline == LDISC_RAW ) {
 940        pBuf = up->rawbuf ;
 941        iLen = up->charcount ;
 942    } else {
 943        pBuf = pp->a_lastcode ;
 944        iLen = pp->lencode ;
 945    }
 946
 947    /*
 948     * JJY-200 sends a timestamp every second.
 949     * So, a timestamp is ignored unless it is right after polled.
 950     */
 951    if ( ! up->bPollFlag ) return 0 ;
 952
 953    switch ( up->linecount ) {
 954
 955    case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
 956
 957        if ( iLen != 23 ) {
 958#ifdef DEBUG
 959            if ( debug >= 2 ) {
 960                printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
 961            }
 962#endif
 963            up->lineerror = 1 ;
 964            break ;
 965        }
 966
 967        rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
 968                      &cApostrophe, sStatus, 
 969                      &up->year, &up->month, &up->day, &iWeekday, &up->hour, &up->minute, &up->second ) ;
 970        sStatus[2] = 0 ;
 971        if ( rc != 9 || cApostrophe != '\'' || strcmp( sStatus, "OK" ) != 0
 972          || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
 973          || iWeekday > 6
 974          || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
 975#ifdef DEBUG
 976            if ( debug >= 2 ) {
 977                printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n", sFunctionName,
 978                         rc, cApostrophe, sStatus, up->year, up->month, up->day, iWeekday, up->hour, up->minute, up->second ) ;
 979            }
 980#endif
 981            up->lineerror = 1 ;
 982            break ;
 983        }
 984
 985        up->year += 2000 ;
 986        up->msecond = 0 ;
 987
 988        break ;
 989
 990    default : /* Unexpected reply */
 991
 992        up->lineerror = 1 ;
 993        break ;
 994
 995    }
 996
 997    return 1 ;
 998
 999}
1000
1001/**************************************************************************************************/
1002/*  jjy_poll - called by the transmit procedure                                                   */
1003/**************************************************************************************************/
1004static void
1005jjy_poll ( int unit, struct peer *peer )
1006{
1007
1008	struct jjyunit      *up;
1009	struct refclockproc *pp;
1010
1011	pp = peer->procptr;
1012	up = (struct jjyunit *) pp->unitptr ;
1013
1014	if ( pp->polls > 0  &&  up->linecount == 0 ) {
1015		/*
1016		 * No reply for last command
1017		 */
1018		refclock_report ( peer, CEVNT_TIMEOUT ) ;
1019	}
1020
1021#ifdef DEBUG
1022	if ( debug ) {
1023		printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
1024	}
1025#endif
1026
1027	pp->polls ++ ;
1028
1029    up->bPollFlag = 1 ;
1030	up->linecount = 0 ;
1031	up->lineerror = 0 ;
1032	up->charcount = 0 ;
1033
1034	switch ( up->unittype ) {
1035	
1036	case UNITTYPE_TRISTATE_JJY01 :
1037		jjy_poll_tristate_jjy01  ( unit, peer ) ;
1038		break ;
1039
1040	case UNITTYPE_CDEX_JST2000 :
1041		jjy_poll_cdex_jst2000 ( unit, peer ) ;
1042		break ;
1043
1044	case UNITTYPE_ECHOKEISOKUKI_LT2000 :
1045		jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
1046		break ;
1047
1048    case UNITTYPE_CITIZENTIC_JJY200 :
1049        jjy_poll_citizentic_jjy200 ( unit, peer ) ;
1050        break ;
1051
1052	default :
1053		break ;
1054
1055	}
1056
1057}
1058
1059/**************************************************************************************************/
1060
1061static void
1062jjy_poll_tristate_jjy01  ( int unit, struct peer *peer )
1063{
1064
1065	struct refclockproc *pp;
1066
1067	pp = peer->procptr;
1068
1069	/*
1070	 * Send "date<CR><LF>" command
1071	 */
1072
1073#ifdef DEBUG
1074	if ( debug ) {
1075		printf ( "jjy_poll_tristate_jjy01 (refclock_jjy.c) : send 'date<CR><LF>'\n" ) ;
1076	}
1077#endif
1078
1079	if ( write ( pp->io.fd, "date\r\n",6 ) != 6  ) {
1080		refclock_report ( peer, CEVNT_FAULT ) ;
1081	}
1082
1083}
1084
1085/**************************************************************************************************/
1086
1087static void
1088jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
1089{
1090
1091	struct refclockproc *pp;
1092
1093	pp = peer->procptr;
1094
1095	/*
1096	 * Send "<ENQ>1J<ETX>" command
1097	 */
1098
1099#ifdef DEBUG
1100	if ( debug ) {
1101		printf ( "jjy_poll_cdex_jst2000 (refclock_jjy.c) : send '<ENQ>1J<ETX>'\n" ) ;
1102	}
1103#endif
1104
1105	if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4  ) {
1106		refclock_report ( peer, CEVNT_FAULT ) ;
1107	}
1108
1109}
1110
1111/**************************************************************************************************/
1112
1113static void
1114jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
1115{
1116
1117	struct jjyunit      *up;
1118	struct refclockproc *pp;
1119
1120	char	sCmd[2] ;
1121
1122	pp = peer->procptr;
1123	up = (struct jjyunit *) pp->unitptr ;
1124
1125	/*
1126	 * Send "T" or "C" command
1127	 */
1128
1129	switch ( up->operationmode ) {
1130	case 1 : sCmd[0] = 'T' ; break ;
1131	case 2 : sCmd[0] = 'C' ; break ;
1132	}
1133	sCmd[1] = 0 ;
1134
1135#ifdef DEBUG
1136	if ( debug ) {
1137		printf ( "jjy_poll_echokeisokuki_lt2000 (refclock_jjy.c) : send '%s'\n", sCmd ) ;
1138	}
1139#endif
1140
1141	if ( write ( pp->io.fd, sCmd, 1 ) != 1  ) {
1142		refclock_report ( peer, CEVNT_FAULT ) ;
1143	}
1144
1145}
1146
1147/**************************************************************************************************/
1148
1149static void
1150jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
1151{
1152
1153    /* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
1154
1155}
1156
1157#else
1158int refclock_jjy_bs ;
1159#endif /* REFCLOCK */