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->ttlmax ) ; 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->ttlmax is a mode number specified by "127.127.40.X mode N" in the ntp.conf 206 */ 207 switch ( peer->ttlmax ) { 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->ttlmax ) ; 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->ttlmax is a mode number specified by "127.127.40.X mode N" in the ntp.conf 237 */ 238 switch ( peer->ttlmax ) { 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->ttlmax ) ; 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->msec = up->msecond ; 426 pp->usec = 0; 427 428 /* 429 * JST to UTC 430 */ 431 pp->hour -= 9 ; 432 if ( pp->hour < 0 ) { 433 pp->hour += 24 ; 434 pp->day -- ; 435 if ( pp->day < 1 ) { 436 pp->year -- ; 437 pp->day = ymd2yd ( pp->year, 12, 31 ) ; 438 } 439 } 440 #ifdef DEBUG 441 if ( debug ) { 442 printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d JST ", 443 up->year, up->month, up->day, up->hour, up->minute, up->second ) ; 444 printf ( "( %04d/%03d %02d:%02d:%02d UTC )\n", 445 pp->year, pp->day, pp->hour, pp->minute, pp->second ) ; 446 } 447 #endif 448 449 /* 450 * Process the new sample in the median filter and determine the 451 * timecode timestamp. 452 */ 453 if ( ! refclock_process ( pp ) ) { 454 refclock_report(peer, CEVNT_BADTIME); 455 sprintf ( sLogText, "BAD TIME %04d/%02d/%02d %02d:%02d:%02d JST", 456 up->year, up->month, up->day, up->hour, up->minute, up->second ) ; 457 record_clock_stats ( &peer->srcadr, sLogText ) ; 458 return ; 459 } 460 461 sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d JST", 462 up->year, up->month, up->day, up->hour, up->minute, up->second ) ; 463 record_clock_stats ( &peer->srcadr, sLogText ) ; 464 465 refclock_receive(peer); 466 467 } 468 469 /**************************************************************************************************/ 470 471 static int 472 jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp ) 473 { 474 475 struct jjyunit *up ; 476 struct refclockproc *pp ; 477 struct peer *peer; 478 479 char *pBuf ; 480 int iLen ; 481 int rc ; 482 483 /* 484 * Initialize pointers and read the timecode and timestamp 485 */ 486 peer = (struct peer *) rbufp->recv_srcclock ; 487 pp = peer->procptr ; 488 up = (struct jjyunit *) pp->unitptr ; 489 490 if ( up->linediscipline == LDISC_RAW ) { 491 pBuf = up->rawbuf ; 492 iLen = up->charcount ; 493 } else { 494 pBuf = pp->a_lastcode ; 495 iLen = pp->lencode ; 496 } 497 498 switch ( up->linecount ) { 499 500 case 1 : /* YYYY/MM/DD */ 501 502 if ( iLen < 10 ) { 503 up->lineerror = 1 ; 504 break ; 505 } 506 rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ; 507 if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) { 508 up->lineerror = 1 ; 509 break ; 510 } 511 return 0 ; 512 513 case 2 : /* HH:MM:SS */ 514 515 if ( iLen < 8 ) { 516 up->lineerror = 1 ; 517 break ; 518 } 519 rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ; 520 if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 521 up->lineerror = 1 ; 522 break ; 523 } 524 up->msecond = 0 ; 525 if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) { 526 /* 527 * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously. 528 * But the JJY receiver replies a date and time separately. 529 * Just after midnight transtions, we ignore this time. 530 */ 531 return 0 ; 532 } 533 break ; 534 535 default : /* Unexpected reply */ 536 537 up->lineerror = 1 ; 538 break ; 539 540 } 541 542 return 1 ; 543 544 } 545 546 /**************************************************************************************************/ 547 548 static int 549 jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp ) 550 { 551 552 struct jjyunit *up ; 553 struct refclockproc *pp ; 554 struct peer *peer; 555 556 char *pBuf ; 557 int iLen ; 558 int rc ; 559 560 /* 561 * Initialize pointers and read the timecode and timestamp 562 */ 563 peer = (struct peer *) rbufp->recv_srcclock ; 564 pp = peer->procptr ; 565 up = (struct jjyunit *) pp->unitptr ; 566 567 if ( up->linediscipline == LDISC_RAW ) { 568 pBuf = up->rawbuf ; 569 iLen = up->charcount ; 570 } else { 571 pBuf = pp->a_lastcode ; 572 iLen = pp->lencode ; 573 } 574 575 switch ( up->linecount ) { 576 577 case 1 : /* JYYMMDD HHMMSSS */ 578 579 if ( iLen < 15 ) { 580 up->lineerror = 1 ; 581 break ; 582 } 583 rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d", 584 &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ; 585 if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 586 || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 587 up->lineerror = 1 ; 588 break ; 589 } 590 up->year += 2000 ; 591 up->msecond *= 100 ; 592 break ; 593 594 default : /* Unexpected reply */ 595 596 up->lineerror = 1 ; 597 break ; 598 599 } 600 601 return 1 ; 602 603 } 604 605 /**************************************************************************************************/ 606 /* jjy_poll - called by the transmit procedure */ 607 /**************************************************************************************************/ 608 static void 609 jjy_poll ( int unit, struct peer *peer ) 610 { 611 612 struct jjyunit *up; 613 struct refclockproc *pp; 614 615 pp = peer->procptr; 616 up = (struct jjyunit *) pp->unitptr ; 617 618 if ( pp->polls > 0 && up->linecount == 0 ) { 619 /* 620 * No reply for last command 621 */ 622 refclock_report ( peer, CEVNT_TIMEOUT ) ; 623 } 624 625 #ifdef DEBUG 626 if ( debug ) { 627 printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ; 628 } 629 #endif 630 631 pp->polls ++ ; 632 633 up->linecount = 0 ; 634 up->lineerror = 0 ; 635 up->charcount = 0 ; 636 637 switch ( up->unittype ) { 638 639 case UNITTYPE_TRISTATE_JJY01 : 640 jjy_poll_tristate_jjy01 ( unit, peer ) ; 641 break ; 642 643 case UNITTYPE_CDEX_JST2000 : 644 jjy_poll_cdex_jst2000 ( unit, peer ) ; 645 break ; 646 647 default : 648 break ; 649 650 } 651 652 } 653 654 /**************************************************************************************************/ 655 656 static void 657 jjy_poll_tristate_jjy01 ( int unit, struct peer *peer ) 658 { 659 660 struct jjyunit *up; 661 struct refclockproc *pp; 662 663 pp = peer->procptr; 664 up = (struct jjyunit *) pp->unitptr ; 665 666 /* 667 * Send "date<CR><LF>" command 668 */ 669 670 if ( write ( pp->io.fd, "date\r\n",6 ) != 6 ) { 671 refclock_report ( peer, CEVNT_FAULT ) ; 672 } 673 674 /* 675 * Send "stim<CR><LF>" or "time<CR><LF>" command 676 */ 677 678 if ( up->version >= 100 ) { 679 if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) { 680 refclock_report ( peer, CEVNT_FAULT ) ; 681 } 682 } else { 683 if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) { 684 refclock_report ( peer, CEVNT_FAULT ) ; 685 } 686 } 687 688 } 689 690 /**************************************************************************************************/ 691 692 static void 693 jjy_poll_cdex_jst2000 ( int unit, struct peer *peer ) 694 { 695 696 struct refclockproc *pp; 697 698 pp = peer->procptr; 699 700 /* 701 * Send "<ENQ>1J<ETX>" command 702 */ 703 704 if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) { 705 refclock_report ( peer, CEVNT_FAULT ) ; 706 } 707 708 } 709 710 #else 711 int refclock_jjy_bs ; 712 #endif /* REFCLOCK */ 713