Annotation of embedaddon/ntp/ntpd/refclock_jjy.c, revision 1.1
1.1 ! misho 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 takao_abe@xurb.jp */
! 45: /* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */
! 46: /* */
! 47: /* The email address abetakao@bea.hi-ho.ne.jp is never read */
! 48: /* from 2010, because a few filtering rule are provided by the */
! 49: /* "hi-ho.ne.jp", and lots of spam mail are reached. */
! 50: /* New email address for supporting the refclock_jjy is */
! 51: /* takao_abe@xurb.jp */
! 52: /* */
! 53: /**********************************************************************/
! 54: /* */
! 55: /* History */
! 56: /* */
! 57: /* 2001/07/15 */
! 58: /* [New] Support the Tristate Ltd. JJY receiver */
! 59: /* */
! 60: /* 2001/08/04 */
! 61: /* [Change] Log to clockstats even if bad reply */
! 62: /* [Fix] PRECISION = (-3) (about 100 ms) */
! 63: /* [Add] Support the C-DEX Co.Ltd. JJY receiver */
! 64: /* */
! 65: /* 2001/12/04 */
! 66: /* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */
! 67: /* */
! 68: /* 2002/07/12 */
! 69: /* [Fix] Portability for FreeBSD ( patched by the user ) */
! 70: /* */
! 71: /* 2004/10/31 */
! 72: /* [Change] Command send timing for the Tristate Ltd. JJY receiver */
! 73: /* JJY-01 ( Firmware version 2.01 ) */
! 74: /* Thanks to Andy Taki for testing under FreeBSD */
! 75: /* */
! 76: /* 2004/11/28 */
! 77: /* [Add] Support the Echo Keisokuki LT-2000 receiver */
! 78: /* */
! 79: /* 2006/11/04 */
! 80: /* [Fix] C-DEX JST2000 */
! 81: /* Thanks to Hideo Kuramatsu for the patch */
! 82: /* */
! 83: /* 2009/04/05 */
! 84: /* [Add] Support the CITIZEN T.I.C JJY-200 receiver */
! 85: /* */
! 86: /* 2010/11/20 */
! 87: /* [Change] Bug 1618 ( Harmless ) */
! 88: /* Code clean up ( Remove unreachable codes ) in */
! 89: /* jjy_start() */
! 90: /* [Change] Change clockstats format of the Tristate JJY01/02 */
! 91: /* Issues more command to get the status of the receiver */
! 92: /* when "fudge 127.127.40.X flag1 1" is specified */
! 93: /* ( DATE,STIM -> DCST,STUS,DATE,STIM ) */
! 94: /* */
! 95: /**********************************************************************/
! 96:
! 97: #ifdef HAVE_CONFIG_H
! 98: #include <config.h>
! 99: #endif
! 100:
! 101: #if defined(REFCLOCK) && defined(CLOCK_JJY)
! 102:
! 103: #include <stdio.h>
! 104: #include <ctype.h>
! 105: #include <string.h>
! 106: #include <sys/time.h>
! 107: #include <time.h>
! 108:
! 109: #include "ntpd.h"
! 110: #include "ntp_io.h"
! 111: #include "ntp_tty.h"
! 112: #include "ntp_refclock.h"
! 113: #include "ntp_calendar.h"
! 114: #include "ntp_stdlib.h"
! 115:
! 116: /**********************************************************************/
! 117: /* */
! 118: /* The Tristate Ltd. JJY receiver JJY01 */
! 119: /* */
! 120: /* Command Response Remarks */
! 121: /* ------------ ---------------------- --------------------- */
! 122: /* dcst<CR><LF> VALID|INVALID<CR><LF> */
! 123: /* stus<CR><LF> ADJUSTED|UNADJUSTED<CR><LF> */
! 124: /* date<CR><LF> YYYY/MM/DD XXX<CR><LF> */
! 125: /* time<CR><LF> HH:MM:SS<CR><LF> */
! 126: /* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */
! 127: /* */
! 128: /* During synchronization after a receiver is turned on, */
! 129: /* It replies the past time from 2000/01/01 00:00:00. */
! 130: /* The function "refclock_process" checks the time and tells */
! 131: /* as an insanity time. */
! 132: /* */
! 133: /**********************************************************************/
! 134: /* */
! 135: /* The C-DEX Co. Ltd. JJY receiver JST2000 */
! 136: /* */
! 137: /* Command Response Remarks */
! 138: /* ------------ ---------------------- --------------------- */
! 139: /* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
! 140: /* */
! 141: /**********************************************************************/
! 142: /* */
! 143: /* The Echo Keisokuki Co. Ltd. JJY receiver LT2000 */
! 144: /* */
! 145: /* Command Response Remarks */
! 146: /* ------------ ---------------------- --------------------- */
! 147: /* # Mode 1 (Request&Send) */
! 148: /* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */
! 149: /* C Mode 2 (Continuous) */
! 150: /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
! 151: /* <SUB> Second signal */
! 152: /* */
! 153: /**********************************************************************/
! 154: /* */
! 155: /* The CITIZEN T.I.C CO., LTD. JJY receiver JJY200 */
! 156: /* */
! 157: /* Command Response Remarks */
! 158: /* ------------ ---------------------- --------------------- */
! 159: /* 'XX YY/MM/DD W HH:MM:SS<CR> */
! 160: /* XX: OK|NG|ER */
! 161: /* W: 0(Monday)-6(Sunday) */
! 162: /* */
! 163: /**********************************************************************/
! 164:
! 165: /*
! 166: * Interface definitions
! 167: */
! 168: #define DEVICE "/dev/jjy%d" /* device name and unit */
! 169: #define SPEED232 B9600 /* uart speed (9600 baud) */
! 170: #define SPEED232_TRISTATE_JJY01 B9600 /* UART speed (9600 baud) */
! 171: #define SPEED232_CDEX_JST2000 B9600 /* UART speed (9600 baud) */
! 172: #define SPEED232_ECHOKEISOKUKI_LT2000 B9600 /* UART speed (9600 baud) */
! 173: #define SPEED232_CITIZENTIC_JJY200 B4800 /* UART speed (4800 baud) */
! 174: #define REFID "JJY" /* reference ID */
! 175: #define DESCRIPTION "JJY Receiver"
! 176: #define PRECISION (-3) /* precision assumed (about 100 ms) */
! 177:
! 178: /*
! 179: * JJY unit control structure
! 180: */
! 181: struct jjyunit {
! 182: char unittype ; /* UNITTYPE_XXXXXXXXXX */
! 183: short operationmode ; /* Echo Keisokuki LT-2000 : 1 or 2 */
! 184: short version ;
! 185: short linediscipline ; /* LDISC_CLK or LDISC_RAW */
! 186: char bPollFlag ; /* Set by jjy_pool and Reset by jjy_receive */
! 187: int linecount ;
! 188: int lineerror ;
! 189: int year, month, day, hour, minute, second, msecond ;
! 190: /* LDISC_RAW only */
! 191: #define MAX_LINECOUNT 8
! 192: #define MAX_RAWBUF 64
! 193: int lineexpect ;
! 194: int charexpect [ MAX_LINECOUNT ] ;
! 195: int charcount ;
! 196: char rawbuf [ MAX_RAWBUF ] ;
! 197: };
! 198:
! 199: #define UNITTYPE_TRISTATE_JJY01 1
! 200: #define UNITTYPE_CDEX_JST2000 2
! 201: #define UNITTYPE_ECHOKEISOKUKI_LT2000 3
! 202: #define UNITTYPE_CITIZENTIC_JJY200 4
! 203:
! 204: /*
! 205: * Function prototypes
! 206: */
! 207: static int jjy_start (int, struct peer *);
! 208: static void jjy_shutdown (int, struct peer *);
! 209: static void jjy_poll (int, struct peer *);
! 210: static void jjy_poll_tristate_jjy01 (int, struct peer *);
! 211: static void jjy_poll_cdex_jst2000 (int, struct peer *);
! 212: static void jjy_poll_echokeisokuki_lt2000(int, struct peer *);
! 213: static void jjy_poll_citizentic_jjy200 (int, struct peer *);
! 214: static void jjy_receive (struct recvbuf *);
! 215: static int jjy_receive_tristate_jjy01 (struct recvbuf *);
! 216: static int jjy_receive_cdex_jst2000 (struct recvbuf *);
! 217: static int jjy_receive_echokeisokuki_lt2000 (struct recvbuf *);
! 218: static int jjy_receive_citizentic_jjy200 (struct recvbuf *);
! 219:
! 220: static void printableString ( char*, int, char*, int ) ;
! 221:
! 222: /*
! 223: * Transfer vector
! 224: */
! 225: struct refclock refclock_jjy = {
! 226: jjy_start, /* start up driver */
! 227: jjy_shutdown, /* shutdown driver */
! 228: jjy_poll, /* transmit poll message */
! 229: noentry, /* not used */
! 230: noentry, /* not used */
! 231: noentry, /* not used */
! 232: NOFLAGS /* not used */
! 233: };
! 234:
! 235: /*
! 236: * Start up driver return code
! 237: */
! 238: #define RC_START_SUCCESS 1
! 239: #define RC_START_ERROR 0
! 240:
! 241: /*
! 242: * Local constants definition
! 243: */
! 244:
! 245: #define MAX_LOGTEXT 64
! 246:
! 247: /*
! 248: * Tristate JJY01/JJY02 constants definition
! 249: */
! 250:
! 251: #define TS_JJY01_COMMAND_NUMBER_DATE 1
! 252: #define TS_JJY01_COMMAND_NUMBER_TIME 2
! 253: #define TS_JJY01_COMMAND_NUMBER_STIM 3
! 254: #define TS_JJY01_COMMAND_NUMBER_STUS 4
! 255: #define TS_JJY01_COMMAND_NUMBER_DCST 5
! 256:
! 257: #define TS_JJY01_REPLY_DATE "yyyy/mm/dd www\r\n"
! 258: #define TS_JJY01_REPLY_STIM "hh:mm:ss\r\n"
! 259: #define TS_JJY01_REPLY_STUS_YES "adjusted\r\n"
! 260: #define TS_JJY01_REPLY_STUS_NO "unadjusted\r\n"
! 261: #define TS_JJY01_REPLY_DCST_VALID "valid\r\n"
! 262: #define TS_JJY01_REPLY_DCST_INVALID "invalid\r\n"
! 263:
! 264: #define TS_JJY01_REPLY_LENGTH_DATE 14 /* Length without <CR><LF> */
! 265: #define TS_JJY01_REPLY_LENGTH_STIM 8 /* Length without <CR><LF> */
! 266: #define TS_JJY01_REPLY_LENGTH_STUS_YES 8 /* Length without <CR><LF> */
! 267: #define TS_JJY01_REPLY_LENGTH_STUS_NO 10 /* Length without <CR><LF> */
! 268: #define TS_JJY01_REPLY_LENGTH_DCST_VALID 5 /* Length without <CR><LF> */
! 269: #define TS_JJY01_REPLY_LENGTH_DCST_INVALID 7 /* Length without <CR><LF> */
! 270:
! 271: static struct
! 272: {
! 273: char commandNumber ;
! 274: char *commandLog ;
! 275: char *command ;
! 276: int commandLength ;
! 277: } tristate_jjy01_command_sequence[] =
! 278: {
! 279: /* dcst<CR><LF> -> VALID<CR><LF> or INVALID<CR><LF> */
! 280: { TS_JJY01_COMMAND_NUMBER_DCST, "dcst", "dcst\r\n", 6 },
! 281: /* stus<CR><LF> -> ADJUSTED<CR><LF> or UNADJUSTED<CR><LF> */
! 282: { TS_JJY01_COMMAND_NUMBER_STUS, "stus", "stus\r\n", 6 },
! 283: /* date<CR><LF> -> YYYY/MM/DD WWW<CR><LF> */
! 284: { TS_JJY01_COMMAND_NUMBER_DATE, "date", "date\r\n", 6 },
! 285: /* stim<CR><LF> -> HH:MM:SS<CR><LF> */
! 286: { TS_JJY01_COMMAND_NUMBER_STIM, "stim", "stim\r\n", 6 },
! 287: { 0 , NULL , NULL , 0 }
! 288: } ;
! 289:
! 290:
! 291: /**************************************************************************************************/
! 292: /* jjy_start - open the devices and initialize data for processing */
! 293: /**************************************************************************************************/
! 294: static int
! 295: jjy_start ( int unit, struct peer *peer )
! 296: {
! 297:
! 298: struct jjyunit *up ;
! 299: struct refclockproc *pp ;
! 300: int fd ;
! 301: char *pDeviceName ;
! 302: short iDiscipline ;
! 303: int iSpeed232 ;
! 304:
! 305: #ifdef DEBUG
! 306: if ( debug ) {
! 307: printf ( "jjy_start (refclock_jjy.c) : %s mode=%d ", ntoa(&peer->srcadr), peer->ttl ) ;
! 308: printf ( DEVICE, unit ) ;
! 309: printf ( "\n" ) ;
! 310: }
! 311: #endif
! 312: /*
! 313: * Open serial port
! 314: */
! 315: pDeviceName = emalloc ( strlen(DEVICE) + 10 );
! 316: snprintf ( pDeviceName, strlen(DEVICE) + 10, DEVICE, unit ) ;
! 317:
! 318: /*
! 319: * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
! 320: */
! 321: switch ( peer->ttl ) {
! 322: case 0 :
! 323: case 1 :
! 324: iDiscipline = LDISC_CLK ;
! 325: iSpeed232 = SPEED232_TRISTATE_JJY01 ;
! 326: break ;
! 327: case 2 :
! 328: iDiscipline = LDISC_RAW ;
! 329: iSpeed232 = SPEED232_CDEX_JST2000 ;
! 330: break ;
! 331: case 3 :
! 332: iDiscipline = LDISC_CLK ;
! 333: iSpeed232 = SPEED232_ECHOKEISOKUKI_LT2000 ;
! 334: break ;
! 335: case 4 :
! 336: iDiscipline = LDISC_CLK ;
! 337: iSpeed232 = SPEED232_CITIZENTIC_JJY200 ;
! 338: break ;
! 339: default :
! 340: msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
! 341: ntoa(&peer->srcadr), peer->ttl ) ;
! 342: free ( (void*) pDeviceName ) ;
! 343: return RC_START_ERROR ;
! 344: }
! 345:
! 346: if ( ! ( fd = refclock_open ( pDeviceName, iSpeed232, iDiscipline ) ) ) {
! 347: free ( (void*) pDeviceName ) ;
! 348: return RC_START_ERROR ;
! 349: }
! 350: free ( (void*) pDeviceName ) ;
! 351:
! 352: /*
! 353: * Allocate and initialize unit structure
! 354: */
! 355: up = emalloc (sizeof(*up));
! 356: memset ( up, 0, sizeof(*up) ) ;
! 357: up->linediscipline = iDiscipline ;
! 358:
! 359: /*
! 360: * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
! 361: */
! 362: switch ( peer->ttl ) {
! 363: case 0 :
! 364: /*
! 365: * The mode 0 is a default clock type at this time.
! 366: * But this will be change to auto-detect mode in the future.
! 367: */
! 368: case 1 :
! 369: up->unittype = UNITTYPE_TRISTATE_JJY01 ;
! 370: up->version = 100 ;
! 371: /* 2010/11/20 */
! 372: /* Command sequence is defined by the struct tristate_jjy01_command_sequence, */
! 373: /* and the following 3 lines are not used in the mode LDISC_CLK. */
! 374: /* up->lineexpect = 2 ; */
! 375: /* up->charexpect[0] = 14 ; */ /* YYYY/MM/DD WWW<CR><LF> */
! 376: /* up->charexpect[1] = 8 ; */ /* HH:MM:SS<CR><LF> */
! 377: break ;
! 378: case 2 :
! 379: up->unittype = UNITTYPE_CDEX_JST2000 ;
! 380: up->lineexpect = 1 ;
! 381: up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
! 382: break ;
! 383: case 3 :
! 384: up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
! 385: up->operationmode = 2 ; /* Mode 2 : Continuous mode */
! 386: up->lineexpect = 1 ;
! 387: switch ( up->operationmode ) {
! 388: case 1 :
! 389: up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
! 390: break ;
! 391: case 2 :
! 392: up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
! 393: break ;
! 394: }
! 395: break ;
! 396: case 4 :
! 397: up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
! 398: up->lineexpect = 1 ;
! 399: up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
! 400: break ;
! 401:
! 402: /* 2010/11/20 */
! 403: /* The "default:" section of this switch block is never executed, */
! 404: /* because the former switch block traps the same "default:" case. */
! 405: /* This "default:" section codes are removed to avoid spending time */
! 406: /* in the future looking, though the codes are functionally harmless. */
! 407:
! 408: }
! 409:
! 410: pp = peer->procptr ;
! 411: pp->unitptr = (caddr_t) up ;
! 412: pp->io.clock_recv = jjy_receive ;
! 413: pp->io.srcclock = (caddr_t) peer ;
! 414: pp->io.datalen = 0 ;
! 415: pp->io.fd = fd ;
! 416: if ( ! io_addclock(&pp->io) ) {
! 417: close ( fd ) ;
! 418: pp->io.fd = -1 ;
! 419: free ( up ) ;
! 420: pp->unitptr = NULL ;
! 421: return RC_START_ERROR ;
! 422: }
! 423:
! 424: /*
! 425: * Initialize miscellaneous variables
! 426: */
! 427: peer->precision = PRECISION ;
! 428: peer->burst = 1 ;
! 429: pp->clockdesc = DESCRIPTION ;
! 430: memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
! 431:
! 432: return RC_START_SUCCESS ;
! 433:
! 434: }
! 435:
! 436:
! 437: /**************************************************************************************************/
! 438: /* jjy_shutdown - shutdown the clock */
! 439: /**************************************************************************************************/
! 440: static void
! 441: jjy_shutdown ( int unit, struct peer *peer )
! 442: {
! 443:
! 444: struct jjyunit *up;
! 445: struct refclockproc *pp;
! 446:
! 447: pp = peer->procptr ;
! 448: up = (struct jjyunit *) pp->unitptr ;
! 449: if ( -1 != pp->io.fd )
! 450: io_closeclock ( &pp->io ) ;
! 451: if ( NULL != up )
! 452: free ( up ) ;
! 453:
! 454: }
! 455:
! 456:
! 457: /**************************************************************************************************/
! 458: /* jjy_receive - receive data from the serial interface */
! 459: /**************************************************************************************************/
! 460: static void
! 461: jjy_receive ( struct recvbuf *rbufp )
! 462: {
! 463:
! 464: struct jjyunit *up ;
! 465: struct refclockproc *pp ;
! 466: struct peer *peer;
! 467:
! 468: l_fp tRecvTimestamp; /* arrival timestamp */
! 469: int rc ;
! 470: char sLogText [ MAX_LOGTEXT ] ;
! 471: int i, bCntrlChar ;
! 472:
! 473: /*
! 474: * Initialize pointers and read the timecode and timestamp
! 475: */
! 476: peer = (struct peer *) rbufp->recv_srcclock ;
! 477: pp = peer->procptr ;
! 478: up = (struct jjyunit *) pp->unitptr ;
! 479:
! 480: /*
! 481: * Get next input line
! 482: */
! 483: pp->lencode = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
! 484:
! 485: if ( up->linediscipline == LDISC_RAW ) {
! 486: /*
! 487: * The reply with <STX> and <ETX> may give a blank line
! 488: */
! 489: if ( pp->lencode == 0 && up->charcount == 0 ) return ;
! 490: /*
! 491: * Copy received charaters to temporary buffer
! 492: */
! 493: for ( i = 0 ;
! 494: i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ;
! 495: i ++ , up->charcount ++ ) {
! 496: up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
! 497: }
! 498: while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
! 499: for ( i = 0 ; i < up->charcount - 1 ; i ++ )
! 500: up->rawbuf[i] = up->rawbuf[i+1] ;
! 501: up->charcount -- ;
! 502: }
! 503: bCntrlChar = 0 ;
! 504: for ( i = 0 ; i < up->charcount ; i ++ ) {
! 505: if ( up->rawbuf[i] < ' ' ) {
! 506: bCntrlChar = 1 ;
! 507: break ;
! 508: }
! 509: }
! 510: if ( pp->lencode > 0 && up->linecount < up->lineexpect ) {
! 511: if ( bCntrlChar == 0 &&
! 512: up->charcount < up->charexpect[up->linecount] )
! 513: return ;
! 514: }
! 515: up->rawbuf[up->charcount] = 0 ;
! 516: } else {
! 517: /*
! 518: * The reply with <CR><LF> gives a blank line
! 519: */
! 520: if ( pp->lencode == 0 ) return ;
! 521: }
! 522: /*
! 523: * We get down to business
! 524: */
! 525:
! 526: pp->lastrec = tRecvTimestamp ;
! 527:
! 528: up->linecount ++ ;
! 529:
! 530: if ( up->lineerror != 0 ) return ;
! 531:
! 532: switch ( up->unittype ) {
! 533:
! 534: case UNITTYPE_TRISTATE_JJY01 :
! 535: rc = jjy_receive_tristate_jjy01 ( rbufp ) ;
! 536: break ;
! 537:
! 538: case UNITTYPE_CDEX_JST2000 :
! 539: rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
! 540: break ;
! 541:
! 542: case UNITTYPE_ECHOKEISOKUKI_LT2000 :
! 543: rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
! 544: break ;
! 545:
! 546: case UNITTYPE_CITIZENTIC_JJY200 :
! 547: rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
! 548: break ;
! 549:
! 550: default :
! 551: rc = 0 ;
! 552: break ;
! 553:
! 554: }
! 555:
! 556: if ( up->linediscipline == LDISC_RAW ) {
! 557: if ( up->linecount <= up->lineexpect &&
! 558: up->charcount > up->charexpect[up->linecount-1] ) {
! 559: for ( i = 0 ;
! 560: i < up->charcount - up->charexpect[up->linecount-1] ;
! 561: i ++ ) {
! 562: up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
! 563: }
! 564: up->charcount -= up->charexpect[up->linecount-1] ;
! 565: } else {
! 566: up->charcount = 0 ;
! 567: }
! 568: }
! 569:
! 570: if ( rc == 0 )
! 571: return ;
! 572:
! 573: up->bPollFlag = 0 ;
! 574:
! 575: if ( up->lineerror != 0 ) {
! 576: refclock_report ( peer, CEVNT_BADREPLY ) ;
! 577: strncpy ( sLogText, "BAD REPLY [",
! 578: sizeof( sLogText ) ) ;
! 579: if ( up->linediscipline == LDISC_RAW ) {
! 580: strncat ( sLogText, up->rawbuf,
! 581: sizeof( sLogText ) -
! 582: strlen ( sLogText ) - 1 ) ;
! 583: } else {
! 584: strncat ( sLogText, pp->a_lastcode,
! 585: sizeof( sLogText ) -
! 586: strlen ( sLogText ) - 1 ) ;
! 587: }
! 588: sLogText[MAX_LOGTEXT-1] = 0 ;
! 589: if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 )
! 590: strncat ( sLogText, "]",
! 591: sizeof( sLogText ) -
! 592: strlen ( sLogText ) - 1 ) ;
! 593: record_clock_stats ( &peer->srcadr, sLogText ) ;
! 594: return ;
! 595: }
! 596:
! 597: pp->year = up->year ;
! 598: pp->day = ymd2yd ( up->year, up->month, up->day ) ;
! 599: pp->hour = up->hour ;
! 600: pp->minute = up->minute ;
! 601: pp->second = up->second ;
! 602: pp->nsec = up->msecond * 1000000;
! 603:
! 604: /*
! 605: * JST to UTC
! 606: */
! 607: pp->hour -= 9 ;
! 608: if ( pp->hour < 0 ) {
! 609: pp->hour += 24 ;
! 610: pp->day -- ;
! 611: if ( pp->day < 1 ) {
! 612: pp->year -- ;
! 613: pp->day = ymd2yd ( pp->year, 12, 31 ) ;
! 614: }
! 615: }
! 616: #ifdef DEBUG
! 617: if ( debug ) {
! 618: printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST ",
! 619: up->year, up->month, up->day, up->hour,
! 620: up->minute, up->second, up->msecond/100 ) ;
! 621: printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
! 622: pp->year, pp->day, pp->hour, pp->minute,
! 623: pp->second, (int)(pp->nsec/100000000) ) ;
! 624: }
! 625: #endif
! 626:
! 627: /*
! 628: * Process the new sample in the median filter and determine the
! 629: * timecode timestamp.
! 630: */
! 631:
! 632: snprintf ( sLogText, sizeof(sLogText),
! 633: "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
! 634: up->year, up->month, up->day,
! 635: up->hour, up->minute, up->second, up->msecond/100 ) ;
! 636: record_clock_stats ( &peer->srcadr, sLogText ) ;
! 637:
! 638: if ( ! refclock_process ( pp ) ) {
! 639: refclock_report(peer, CEVNT_BADTIME);
! 640: return ;
! 641: }
! 642:
! 643: pp->lastref = pp->lastrec;
! 644: refclock_receive(peer);
! 645:
! 646: }
! 647:
! 648: /**************************************************************************************************/
! 649:
! 650: static int
! 651: jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
! 652: {
! 653:
! 654: static char *sFunctionName = "jjy_receive_tristate_jjy01" ;
! 655:
! 656: struct jjyunit *up ;
! 657: struct refclockproc *pp ;
! 658: struct peer *peer;
! 659:
! 660: char *pBuf ;
! 661: int iLen ;
! 662: int rc ;
! 663:
! 664: int bOverMidnight = 0 ;
! 665:
! 666: char sLogText [ MAX_LOGTEXT ], sReplyText [ MAX_LOGTEXT ] ;
! 667:
! 668: char *pCmd ;
! 669: int iCmdLen ;
! 670:
! 671: /*
! 672: * Initialize pointers and read the timecode and timestamp
! 673: */
! 674: peer = (struct peer *) rbufp->recv_srcclock ;
! 675: pp = peer->procptr ;
! 676: up = (struct jjyunit *) pp->unitptr ;
! 677:
! 678: if ( up->linediscipline == LDISC_RAW ) {
! 679: pBuf = up->rawbuf ;
! 680: iLen = up->charcount ;
! 681: } else {
! 682: pBuf = pp->a_lastcode ;
! 683: iLen = pp->lencode ;
! 684: }
! 685:
! 686: switch ( tristate_jjy01_command_sequence[up->linecount-1].commandNumber ) {
! 687:
! 688: case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */
! 689:
! 690: if ( iLen != TS_JJY01_REPLY_LENGTH_DATE ) {
! 691: up->lineerror = 1 ;
! 692: break ;
! 693: }
! 694:
! 695: rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year,
! 696: &up->month, &up->day ) ;
! 697: if ( rc != 3 || up->year < 2000 || up->month < 1 ||
! 698: up->month > 12 || up->day < 1 || up->day > 31 ) {
! 699: up->lineerror = 1 ;
! 700: break ;
! 701: }
! 702:
! 703: /*** Start of modification on 2004/10/31 ***/
! 704: /*
! 705: * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
! 706: * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
! 707: * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
! 708: * so this driver issues the second command "stim" after the reply of the first command "date".
! 709: */
! 710:
! 711: /*** 2010/11/20 ***/
! 712: /*
! 713: * Codes of a next command issue are moved to the end of this function.
! 714: */
! 715:
! 716: /*** End of modification ***/
! 717:
! 718: break ;
! 719:
! 720: case TS_JJY01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
! 721: case TS_JJY01_COMMAND_NUMBER_STIM : /* HH:MM:SS */
! 722:
! 723: if ( iLen != TS_JJY01_REPLY_LENGTH_STIM ) {
! 724: up->lineerror = 1 ;
! 725: break ;
! 726: }
! 727:
! 728: rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour,
! 729: &up->minute, &up->second ) ;
! 730: if ( rc != 3 || up->hour > 23 || up->minute > 59 ||
! 731: up->second > 60 ) {
! 732: up->lineerror = 1 ;
! 733: break ;
! 734: }
! 735:
! 736: up->msecond = 0 ;
! 737: if ( up->hour == 0 && up->minute == 0 &&
! 738: up->second <= 2 ) {
! 739: /*
! 740: * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver separately,
! 741: * and the JJY receiver replies a date and time separately.
! 742: * Just after midnight transitions, we ignore this time.
! 743: */
! 744: bOverMidnight = 1 ;
! 745: }
! 746: break ;
! 747:
! 748: case TS_JJY01_COMMAND_NUMBER_STUS :
! 749:
! 750: if ( ( iLen == TS_JJY01_REPLY_LENGTH_STUS_YES
! 751: && strncmp( pBuf, TS_JJY01_REPLY_STUS_YES,
! 752: TS_JJY01_REPLY_LENGTH_STUS_YES ) == 0 )
! 753: || ( iLen == TS_JJY01_REPLY_LENGTH_STUS_NO
! 754: && strncmp( pBuf, TS_JJY01_REPLY_STUS_NO,
! 755: TS_JJY01_REPLY_LENGTH_STUS_NO ) == 0 ) ) {
! 756: /* Good */
! 757: } else {
! 758: up->lineerror = 1 ;
! 759: break ;
! 760: }
! 761:
! 762: break ;
! 763:
! 764: case TS_JJY01_COMMAND_NUMBER_DCST :
! 765:
! 766: if ( ( iLen == TS_JJY01_REPLY_LENGTH_DCST_VALID
! 767: && strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID,
! 768: TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0 )
! 769: || ( iLen == TS_JJY01_REPLY_LENGTH_DCST_INVALID
! 770: && strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID,
! 771: TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) ) {
! 772: /* Good */
! 773: } else {
! 774: up->lineerror = 1 ;
! 775: break ;
! 776: }
! 777:
! 778: break ;
! 779:
! 780: default : /* Unexpected reply */
! 781:
! 782: up->lineerror = 1 ;
! 783: break ;
! 784:
! 785: }
! 786:
! 787: /* Clockstats Log */
! 788:
! 789: printableString( sReplyText, sizeof(sReplyText), pBuf, iLen ) ;
! 790: snprintf ( sLogText, sizeof(sLogText), "%d: %s -> %c: %s",
! 791: up->linecount,
! 792: tristate_jjy01_command_sequence[up->linecount-1].commandLog,
! 793: ( up->lineerror == 0 )
! 794: ? ( ( bOverMidnight == 0 )
! 795: ? 'O'
! 796: : 'S' )
! 797: : 'X',
! 798: sReplyText ) ;
! 799: record_clock_stats ( &peer->srcadr, sLogText ) ;
! 800:
! 801: /* Check before issue next command */
! 802:
! 803: if ( up->lineerror != 0 ) {
! 804: /* Do not issue next command */
! 805: return 0 ;
! 806: }
! 807:
! 808: if ( bOverMidnight != 0 ) {
! 809: /* Do not issue next command */
! 810: return 0 ;
! 811: }
! 812:
! 813: if ( tristate_jjy01_command_sequence[up->linecount].command == NULL ) {
! 814: /* Command sequence completed */
! 815: return 1 ;
! 816: }
! 817:
! 818: /* Issue next command */
! 819:
! 820: #ifdef DEBUG
! 821: if ( debug ) {
! 822: printf ( "%s (refclock_jjy.c) : send '%s'\n",
! 823: sFunctionName, tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
! 824: }
! 825: #endif
! 826:
! 827: pCmd = tristate_jjy01_command_sequence[up->linecount].command ;
! 828: iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
! 829: if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
! 830: refclock_report ( peer, CEVNT_FAULT ) ;
! 831: }
! 832:
! 833: return 0 ;
! 834:
! 835: }
! 836:
! 837: /**************************************************************************************************/
! 838:
! 839: static int
! 840: jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
! 841: {
! 842:
! 843: static char *sFunctionName = "jjy_receive_cdex_jst2000" ;
! 844:
! 845: struct jjyunit *up ;
! 846: struct refclockproc *pp ;
! 847: struct peer *peer;
! 848:
! 849: char *pBuf ;
! 850: int iLen ;
! 851: int rc ;
! 852:
! 853: /*
! 854: * Initialize pointers and read the timecode and timestamp
! 855: */
! 856: peer = (struct peer *) rbufp->recv_srcclock ;
! 857: pp = peer->procptr ;
! 858: up = (struct jjyunit *) pp->unitptr ;
! 859:
! 860: if ( up->linediscipline == LDISC_RAW ) {
! 861: pBuf = up->rawbuf ;
! 862: iLen = up->charcount ;
! 863: } else {
! 864: pBuf = pp->a_lastcode ;
! 865: iLen = pp->lencode ;
! 866: }
! 867:
! 868: switch ( up->linecount ) {
! 869:
! 870: case 1 : /* JYYMMDD HHMMSSS */
! 871:
! 872: if ( iLen != 15 ) {
! 873: #ifdef DEBUG
! 874: if ( debug >= 2 ) {
! 875: printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
! 876: sFunctionName, iLen ) ;
! 877: }
! 878: #endif
! 879: up->lineerror = 1 ;
! 880: break ;
! 881: }
! 882: rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
! 883: &up->year, &up->month, &up->day,
! 884: &up->hour, &up->minute, &up->second,
! 885: &up->msecond ) ;
! 886: if ( rc != 7 || up->month < 1 || up->month > 12 ||
! 887: up->day < 1 || up->day > 31 || up->hour > 23 ||
! 888: up->minute > 59 || up->second > 60 ) {
! 889: #ifdef DEBUG
! 890: if ( debug >= 2 ) {
! 891: printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n",
! 892: sFunctionName, rc, up->year,
! 893: up->month, up->day, up->hour,
! 894: up->minute, up->second,
! 895: up->msecond ) ;
! 896: }
! 897: #endif
! 898: up->lineerror = 1 ;
! 899: break ;
! 900: }
! 901: up->year += 2000 ;
! 902: up->msecond *= 100 ;
! 903: break ;
! 904:
! 905: default : /* Unexpected reply */
! 906:
! 907: up->lineerror = 1 ;
! 908: break ;
! 909:
! 910: }
! 911:
! 912: return 1 ;
! 913:
! 914: }
! 915:
! 916: /**************************************************************************************************/
! 917:
! 918: static int
! 919: jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
! 920: {
! 921:
! 922: static 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", sFunctionName ) ;
! 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 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 char *sFunctionName = "jjy_poll_tristate_jjy01" ;
! 1233:
! 1234: struct jjyunit *up;
! 1235: struct refclockproc *pp;
! 1236:
! 1237: 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: 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( 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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>