/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. /* Copyright (C) 2001-2004, Takao Abe. All rights reserved. */
  7. /* */
  8. /* Permission to use, copy, modify, and distribute this software */
  9. /* and its documentation for any purpose is hereby granted */
  10. /* without fee, provided that the following conditions are met: */
  11. /* */
  12. /* One retains the entire copyright notice properly, and both the */
  13. /* copyright notice and this license. in the documentation and/or */
  14. /* other materials provided with the distribution. */
  15. /* */
  16. /* This software and the name of the author must not be used to */
  17. /* endorse or promote products derived from this software without */
  18. /* prior written permission. */
  19. /* */
  20. /* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED */
  21. /* WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE */
  22. /* IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A */
  23. /* PARTICULAR PURPOSE. */
  24. /* IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT, */
  25. /* INDIRECT, GENERAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
  26. /* ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
  27. /* GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS */
  28. /* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
  29. /* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING */
  30. /* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF */
  31. /* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
  32. /* */
  33. /* This driver is developed in my private time, and is opened as */
  34. /* voluntary contributions for the NTP. */
  35. /* The manufacturer of the JJY receiver has not participated in */
  36. /* a development of this driver. */
  37. /* The manufacturer does not warrant anything about this driver, */
  38. /* and is not liable for anything about this driver. */
  39. /* */
  40. /**********************************************************************/
  41. /* */
  42. /* Author Takao Abe */
  43. /* Email abetakao@bea.hi-ho.ne.jp */
  44. /* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */
  45. /* */
  46. /**********************************************************************/
  47. /* */
  48. /* History */
  49. /* */
  50. /* 2001/07/15 */
  51. /* [New] Support the Tristate Ltd. JJY receiver */
  52. /* */
  53. /* 2001/08/04 */
  54. /* [Change] Log to clockstats even if bad reply */
  55. /* [Fix] PRECISION = (-3) (about 100 ms) */
  56. /* [Add] Support the C-DEX Co.Ltd. JJY receiver */
  57. /* */
  58. /* 2001/12/04 */
  59. /* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */
  60. /* */
  61. /* 2002/07/12 */
  62. /* [Fix] Portability for FreeBSD ( patched by the user ) */
  63. /* */
  64. /* 2004/10/31 */
  65. /* [Change] Command send timing for the Tristate Ltd. JJY receiver */
  66. /* JJY-01 ( Firmware version 2.01 ) */
  67. /* Thanks to Andy Taki for testing under FreeBSD */
  68. /* */
  69. /* 2004/11/28 */
  70. /* [Add] Support the Echo Keisokuki LT-2000 receiver */
  71. /* */
  72. /* 2006/11/04 */
  73. /* [Fix] C-DEX JST2000 */
  74. /* Thanks to Hideo Kuramatsu for the patch */
  75. /* */
  76. /* 2009/04/05 */
  77. /* [Add] Support the CITIZEN T.I.C JJY-200 receiver */
  78. /* */
  79. /**********************************************************************/
  80. #ifdef HAVE_CONFIG_H
  81. #include <config.h>
  82. #endif
  83. #if defined(REFCLOCK) && defined(CLOCK_JJY)
  84. #include <stdio.h>
  85. #include <ctype.h>
  86. #include <string.h>
  87. #include <sys/time.h>
  88. #include <time.h>
  89. #include "ntpd.h"
  90. #include "ntp_io.h"
  91. #include "ntp_tty.h"
  92. #include "ntp_refclock.h"
  93. #include "ntp_calendar.h"
  94. #include "ntp_stdlib.h"
  95. /**********************************************************************/
  96. /* */
  97. /* The Tristate Ltd. JJY receiver JJY01 */
  98. /* */
  99. /* Command Response Remarks */
  100. /* ------------ ---------------------- --------------------- */
  101. /* date<CR><LF> YYYY/MM/DD XXX<CR><LF> */
  102. /* time<CR><LF> HH:MM:SS<CR><LF> */
  103. /* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */
  104. /* */
  105. /* During synchronization after a receiver is turned on, */
  106. /* It replies the past time from 2000/01/01 00:00:00. */
  107. /* The function "refclock_process" checks the time and tells */
  108. /* as an insanity time. */
  109. /* */
  110. /**********************************************************************/
  111. /* */
  112. /* The C-DEX Co. Ltd. JJY receiver JST2000 */
  113. /* */
  114. /* Command Response Remarks */
  115. /* ------------ ---------------------- --------------------- */
  116. /* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
  117. /* */
  118. /**********************************************************************/
  119. /* */
  120. /* The Echo Keisokuki Co. Ltd. JJY receiver LT2000 */
  121. /* */
  122. /* Command Response Remarks */
  123. /* ------------ ---------------------- --------------------- */
  124. /* # Mode 1 (Request&Send) */
  125. /* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */
  126. /* C Mode 2 (Continuous) */
  127. /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
  128. /* <SUB> Second signal */
  129. /* */
  130. /**********************************************************************/
  131. /* */
  132. /* The CITIZEN T.I.C CO., LTD. JJY receiver JJY200 */
  133. /* */
  134. /* Command Response Remarks */
  135. /* ------------ ---------------------- --------------------- */
  136. /* 'XX YY/MM/DD W HH:MM:SS<CR> */
  137. /* XX: OK|NG|ER */
  138. /* W: 0(Monday)-6(Sunday) */
  139. /* */
  140. /**********************************************************************/
  141. /*
  142. * Interface definitions
  143. */
  144. #define DEVICE "/dev/jjy%d" /* device name and unit */
  145. #define SPEED232 B9600 /* uart speed (9600 baud) */
  146. #define SPEED232_TRISTATE_JJY01 B9600 /* UART speed (9600 baud) */
  147. #define SPEED232_CDEX_JST2000 B9600 /* UART speed (9600 baud) */
  148. #define SPEED232_ECHOKEISOKUKI_LT2000 B9600 /* UART speed (9600 baud) */
  149. #define SPEED232_CITIZENTIC_JJY200 B4800 /* UART speed (4800 baud) */
  150. #define REFID "JJY" /* reference ID */
  151. #define DESCRIPTION "JJY Receiver"
  152. #define PRECISION (-3) /* precision assumed (about 100 ms) */
  153. /*
  154. * JJY unit control structure
  155. */
  156. struct jjyunit {
  157. char unittype ; /* UNITTYPE_XXXXXXXXXX */
  158. short operationmode ; /* Echo Keisokuki LT-2000 : 1 or 2 */
  159. short version ;
  160. short linediscipline ; /* LDISC_CLK or LDISC_RAW */
  161. char bPollFlag ; /* Set by jjy_pool and Reset by jjy_receive */
  162. int linecount ;
  163. int lineerror ;
  164. int year, month, day, hour, minute, second, msecond ;
  165. /* LDISC_RAW only */
  166. #define MAX_LINECOUNT 8
  167. #define MAX_RAWBUF 64
  168. int lineexpect ;
  169. int charexpect [ MAX_LINECOUNT ] ;
  170. int charcount ;
  171. char rawbuf [ MAX_RAWBUF ] ;
  172. };
  173. #define UNITTYPE_TRISTATE_JJY01 1
  174. #define UNITTYPE_CDEX_JST2000 2
  175. #define UNITTYPE_ECHOKEISOKUKI_LT2000 3
  176. #define UNITTYPE_CITIZENTIC_JJY200 4
  177. /*
  178. * Function prototypes
  179. */
  180. static int jjy_start P((int, struct peer *));
  181. static void jjy_shutdown P((int, struct peer *));
  182. static void jjy_poll P((int, struct peer *));
  183. static void jjy_poll_tristate_jjy01 P((int, struct peer *));
  184. static void jjy_poll_cdex_jst2000 P((int, struct peer *));
  185. static void jjy_poll_echokeisokuki_lt2000 P((int, struct peer *));
  186. static void jjy_poll_citizentic_jjy200 P((int, struct peer *));
  187. static void jjy_receive P((struct recvbuf *));
  188. static int jjy_receive_tristate_jjy01 P((struct recvbuf *));
  189. static int jjy_receive_cdex_jst2000 P((struct recvbuf *));
  190. static int jjy_receive_echokeisokuki_lt2000 P((struct recvbuf *));
  191. static int jjy_receive_citizentic_jjy200 P((struct recvbuf *));
  192. /*
  193. * Transfer vector
  194. */
  195. struct refclock refclock_jjy = {
  196. jjy_start, /* start up driver */
  197. jjy_shutdown, /* shutdown driver */
  198. jjy_poll, /* transmit poll message */
  199. noentry, /* not used */
  200. noentry, /* not used */
  201. noentry, /* not used */
  202. NOFLAGS /* not used */
  203. };
  204. /*
  205. * Start up driver return code
  206. */
  207. #define RC_START_SUCCESS 1
  208. #define RC_START_ERROR 0
  209. /*
  210. * Local constants definition
  211. */
  212. #define MAX_LOGTEXT 64
  213. /**************************************************************************************************/
  214. /* jjy_start - open the devices and initialize data for processing */
  215. /**************************************************************************************************/
  216. static int
  217. jjy_start ( int unit, struct peer *peer )
  218. {
  219. struct jjyunit *up ;
  220. struct refclockproc *pp ;
  221. int fd ;
  222. char *pDeviceName ;
  223. short iDiscipline ;
  224. int iSpeed232 ;
  225. #ifdef DEBUG
  226. if ( debug ) {
  227. printf ( "jjy_start (refclock_jjy.c) : %s mode=%d ", ntoa(&peer->srcadr), peer->ttl ) ;
  228. printf ( DEVICE, unit ) ;
  229. printf ( "\n" ) ;
  230. }
  231. #endif
  232. /*
  233. * Open serial port
  234. */
  235. if ( ! ( pDeviceName = (char*) emalloc ( strlen(DEVICE) + 10 ) ) ) {
  236. return RC_START_ERROR ;
  237. }
  238. sprintf ( pDeviceName, DEVICE, unit ) ;
  239. /*
  240. * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
  241. */
  242. switch ( peer->ttl ) {
  243. case 0 :
  244. case 1 :
  245. iDiscipline = LDISC_CLK ;
  246. iSpeed232 = SPEED232_TRISTATE_JJY01 ;
  247. break ;
  248. case 2 :
  249. iDiscipline = LDISC_RAW ;
  250. iSpeed232 = SPEED232_CDEX_JST2000 ;
  251. break ;
  252. case 3 :
  253. iDiscipline = LDISC_CLK ;
  254. iSpeed232 = SPEED232_ECHOKEISOKUKI_LT2000 ;
  255. break ;
  256. case 4 :
  257. iDiscipline = LDISC_CLK ;
  258. iSpeed232 = SPEED232_CITIZENTIC_JJY200 ;
  259. break ;
  260. default :
  261. msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
  262. ntoa(&peer->srcadr), peer->ttl ) ;
  263. free ( (void*) pDeviceName ) ;
  264. return RC_START_ERROR ;
  265. }
  266. if ( ! ( fd = refclock_open ( pDeviceName, iSpeed232, iDiscipline ) ) ) {
  267. free ( (void*) pDeviceName ) ;
  268. return RC_START_ERROR ;
  269. }
  270. free ( (void*) pDeviceName ) ;
  271. /*
  272. * Allocate and initialize unit structure
  273. */
  274. if ( ! ( up = (struct jjyunit *) emalloc (sizeof(struct jjyunit)) ) ) {
  275. close ( fd ) ;
  276. return RC_START_ERROR ;
  277. }
  278. memset ( (char*)up, 0, sizeof(struct jjyunit) ) ;
  279. up->linediscipline = iDiscipline ;
  280. /*
  281. * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
  282. */
  283. switch ( peer->ttl ) {
  284. case 0 :
  285. /*
  286. * The mode 0 is a default clock type at this time.
  287. * But this will be change to auto-detect mode in the future.
  288. */
  289. case 1 :
  290. up->unittype = UNITTYPE_TRISTATE_JJY01 ;
  291. up->version = 100 ;
  292. up->lineexpect = 2 ;
  293. up->charexpect[0] = 14 ; /* YYYY/MM/DD WWW<CR><LF> */
  294. up->charexpect[1] = 8 ; /* HH:MM:SS<CR><LF> */
  295. break ;
  296. case 2 :
  297. up->unittype = UNITTYPE_CDEX_JST2000 ;
  298. up->lineexpect = 1 ;
  299. up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
  300. break ;
  301. case 3 :
  302. up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
  303. up->operationmode = 2 ; /* Mode 2 : Continuous mode */
  304. up->lineexpect = 1 ;
  305. switch ( up->operationmode ) {
  306. case 1 :
  307. up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
  308. break ;
  309. case 2 :
  310. up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
  311. break ;
  312. }
  313. break ;
  314. case 4 :
  315. up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
  316. up->lineexpect = 1 ;
  317. up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
  318. break ;
  319. default :
  320. msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
  321. ntoa(&peer->srcadr), peer->ttl ) ;
  322. close ( fd ) ;
  323. free ( (void*) up ) ;
  324. return RC_START_ERROR ;
  325. }
  326. pp = peer->procptr ;
  327. pp->unitptr = (caddr_t) up ;
  328. pp->io.clock_recv = jjy_receive ;
  329. pp->io.srcclock = (caddr_t) peer ;
  330. pp->io.datalen = 0 ;
  331. pp->io.fd = fd ;
  332. if ( ! io_addclock(&pp->io) ) {
  333. close ( fd ) ;
  334. free ( (void*) up ) ;
  335. return RC_START_ERROR ;
  336. }
  337. /*
  338. * Initialize miscellaneous variables
  339. */
  340. peer->precision = PRECISION ;
  341. peer->burst = 1 ;
  342. pp->clockdesc = DESCRIPTION ;
  343. memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
  344. return RC_START_SUCCESS ;
  345. }
  346. /**************************************************************************************************/
  347. /* jjy_shutdown - shutdown the clock */
  348. /**************************************************************************************************/
  349. static void
  350. jjy_shutdown ( int unit, struct peer *peer )
  351. {
  352. struct jjyunit *up;
  353. struct refclockproc *pp;
  354. pp = peer->procptr ;
  355. up = (struct jjyunit *) pp->unitptr ;
  356. io_closeclock ( &pp->io ) ;
  357. free ( (void*) up ) ;
  358. }
  359. /**************************************************************************************************/
  360. /* jjy_receive - receive data from the serial interface */
  361. /**************************************************************************************************/
  362. static void
  363. jjy_receive ( struct recvbuf *rbufp )
  364. {
  365. struct jjyunit *up ;
  366. struct refclockproc *pp ;
  367. struct peer *peer;
  368. l_fp tRecvTimestamp; /* arrival timestamp */
  369. int rc ;
  370. char sLogText [ MAX_LOGTEXT ] ;
  371. int i, bCntrlChar ;
  372. /*
  373. * Initialize pointers and read the timecode and timestamp
  374. */
  375. peer = (struct peer *) rbufp->recv_srcclock ;
  376. pp = peer->procptr ;
  377. up = (struct jjyunit *) pp->unitptr ;
  378. /*
  379. * Get next input line
  380. */
  381. pp->lencode = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
  382. if ( up->linediscipline == LDISC_RAW ) {
  383. /*
  384. * The reply with <STX> and <ETX> may give a blank line
  385. */
  386. if ( pp->lencode == 0 && up->charcount == 0 ) return ;
  387. /*
  388. * Copy received charaters to temporary buffer
  389. */
  390. for ( i = 0 ; i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ; i ++ , up->charcount ++ ) {
  391. up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
  392. }
  393. while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
  394. for ( i = 0 ; i < up->charcount - 1 ; i ++ ) up->rawbuf[i] = up->rawbuf[i+1] ;
  395. up->charcount -- ;
  396. }
  397. bCntrlChar = 0 ;
  398. for ( i = 0 ; i < up->charcount ; i ++ ) {
  399. if ( up->rawbuf[i] < ' ' ) {
  400. bCntrlChar = 1 ;
  401. break ;
  402. }
  403. }
  404. if ( pp->lencode > 0 && up->linecount < up->lineexpect ) {
  405. if ( bCntrlChar == 0 && up->charcount < up->charexpect[up->linecount] ) return ;
  406. }
  407. up->rawbuf[up->charcount] = 0 ;
  408. } else {
  409. /*
  410. * The reply with <CR><LF> gives a blank line
  411. */
  412. if ( pp->lencode == 0 ) return ;
  413. }
  414. /*
  415. * We get down to business
  416. */
  417. pp->lastrec = tRecvTimestamp ;
  418. up->linecount ++ ;
  419. if ( up->lineerror != 0 ) return ;
  420. switch ( up->unittype ) {
  421. case UNITTYPE_TRISTATE_JJY01 :
  422. rc = jjy_receive_tristate_jjy01 ( rbufp ) ;
  423. break ;
  424. case UNITTYPE_CDEX_JST2000 :
  425. rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
  426. break ;
  427. case UNITTYPE_ECHOKEISOKUKI_LT2000 :
  428. rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
  429. break ;
  430. case UNITTYPE_CITIZENTIC_JJY200 :
  431. rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
  432. break ;
  433. default :
  434. rc = 0 ;
  435. break ;
  436. }
  437. if ( up->linediscipline == LDISC_RAW ) {
  438. if ( up->linecount <= up->lineexpect && up->charcount > up->charexpect[up->linecount-1] ) {
  439. for ( i = 0 ; i < up->charcount - up->charexpect[up->linecount-1] ; i ++ ) {
  440. up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
  441. }
  442. up->charcount -= up->charexpect[up->linecount-1] ;
  443. } else {
  444. up->charcount = 0 ;
  445. }
  446. }
  447. if ( rc == 0 ) return ;
  448. up->bPollFlag = 0 ;
  449. if ( up->lineerror != 0 ) {
  450. refclock_report ( peer, CEVNT_BADREPLY ) ;
  451. strcpy ( sLogText, "BAD REPLY [" ) ;
  452. if ( up->linediscipline == LDISC_RAW ) {
  453. strncat ( sLogText, up->rawbuf, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
  454. } else {
  455. strncat ( sLogText, pp->a_lastcode, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
  456. }
  457. sLogText[MAX_LOGTEXT-1] = 0 ;
  458. if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 ) strcat ( sLogText, "]" ) ;
  459. record_clock_stats ( &peer->srcadr, sLogText ) ;
  460. return ;
  461. }
  462. pp->year = up->year ;
  463. pp->day = ymd2yd ( up->year, up->month, up->day ) ;
  464. pp->hour = up->hour ;
  465. pp->minute = up->minute ;
  466. pp->second = up->second ;
  467. pp->nsec = up->msecond * 1000000;
  468. /*
  469. * JST to UTC
  470. */
  471. pp->hour -= 9 ;
  472. if ( pp->hour < 0 ) {
  473. pp->hour += 24 ;
  474. pp->day -- ;
  475. if ( pp->day < 1 ) {
  476. pp->year -- ;
  477. pp->day = ymd2yd ( pp->year, 12, 31 ) ;
  478. }
  479. }
  480. #ifdef DEBUG
  481. if ( debug ) {
  482. printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST ",
  483. up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
  484. printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
  485. pp->year, pp->day, pp->hour, pp->minute, pp->second, (int)(pp->nsec/100000000) ) ;
  486. }
  487. #endif
  488. /*
  489. * Process the new sample in the median filter and determine the
  490. * timecode timestamp.
  491. */
  492. sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
  493. up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
  494. record_clock_stats ( &peer->srcadr, sLogText ) ;
  495. if ( ! refclock_process ( pp ) ) {
  496. refclock_report(peer, CEVNT_BADTIME);
  497. return ;
  498. }
  499. pp->lastref = pp->lastrec;
  500. refclock_receive(peer);
  501. }
  502. /**************************************************************************************************/
  503. static int
  504. jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
  505. {
  506. static char *sFunctionName = "jjy_receive_tristate_jjy01" ;
  507. struct jjyunit *up ;
  508. struct refclockproc *pp ;
  509. struct peer *peer;
  510. char *pBuf ;
  511. int iLen ;
  512. int rc ;
  513. /*
  514. * Initialize pointers and read the timecode and timestamp
  515. */
  516. peer = (struct peer *) rbufp->recv_srcclock ;
  517. pp = peer->procptr ;
  518. up = (struct jjyunit *) pp->unitptr ;
  519. if ( up->linediscipline == LDISC_RAW ) {
  520. pBuf = up->rawbuf ;
  521. iLen = up->charcount ;
  522. } else {
  523. pBuf = pp->a_lastcode ;
  524. iLen = pp->lencode ;
  525. }
  526. switch ( up->linecount ) {
  527. case 1 : /* YYYY/MM/DD WWW */
  528. if ( iLen != 14 ) {
  529. #ifdef DEBUG
  530. if ( debug >= 2 ) {
  531. printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
  532. }
  533. #endif
  534. up->lineerror = 1 ;
  535. break ;
  536. }
  537. rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
  538. if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
  539. #ifdef DEBUG
  540. if ( debug >= 2 ) {
  541. printf ( "%s (refclock_jjy.c) : Date error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
  542. }
  543. #endif
  544. up->lineerror = 1 ;
  545. break ;
  546. }
  547. /*** Start of modification on 2004/10/31 */
  548. /*
  549. * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
  550. * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
  551. * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
  552. * so this driver issues the second command "stim" after the reply of the first command "date".
  553. */
  554. /*
  555. * Send "stim<CR><LF>" or "time<CR><LF>" command
  556. */
  557. if ( up->version >= 100 ) {
  558. #ifdef DEBUG
  559. if ( debug ) {
  560. printf ( "%s (refclock_jjy.c) : send 'stim<CR><LF>'\n", sFunctionName ) ;
  561. }
  562. #endif
  563. if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) {
  564. refclock_report ( peer, CEVNT_FAULT ) ;
  565. }
  566. } else {
  567. #ifdef DEBUG
  568. if ( debug ) {
  569. printf ( "%s (refclock_jjy.c) : send 'time<CR><LF>'\n", sFunctionName ) ;
  570. }
  571. #endif
  572. if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) {
  573. refclock_report ( peer, CEVNT_FAULT ) ;
  574. }
  575. }
  576. /*** End of modification ***/
  577. return 0 ;
  578. case 2 : /* HH:MM:SS */
  579. if ( iLen != 8 ) {
  580. #ifdef DEBUG
  581. if ( debug >= 2 ) {
  582. printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
  583. }
  584. #endif
  585. up->lineerror = 1 ;
  586. break ;
  587. }
  588. rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
  589. if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
  590. #ifdef DEBUG
  591. if ( debug >= 2 ) {
  592. printf ( "%s (refclock_jjy.c) : Time error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
  593. }
  594. #endif
  595. up->lineerror = 1 ;
  596. break ;
  597. }
  598. up->msecond = 0 ;
  599. if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
  600. /*
  601. * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
  602. * But the JJY receiver replies a date and time separately.
  603. * Just after midnight transitions, we ignore this time.
  604. */
  605. return 0 ;
  606. }
  607. break ;
  608. default : /* Unexpected reply */
  609. up->lineerror = 1 ;
  610. break ;
  611. }
  612. return 1 ;
  613. }
  614. /**************************************************************************************************/
  615. static int
  616. jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
  617. {
  618. static char *sFunctionName = "jjy_receive_cdex_jst2000" ;
  619. struct jjyunit *up ;
  620. struct refclockproc *pp ;
  621. struct peer *peer;
  622. char *pBuf ;
  623. int iLen ;
  624. int rc ;
  625. /*
  626. * Initialize pointers and read the timecode and timestamp
  627. */
  628. peer = (struct peer *) rbufp->recv_srcclock ;
  629. pp = peer->procptr ;
  630. up = (struct jjyunit *) pp->unitptr ;
  631. if ( up->linediscipline == LDISC_RAW ) {
  632. pBuf = up->rawbuf ;
  633. iLen = up->charcount ;
  634. } else {
  635. pBuf = pp->a_lastcode ;
  636. iLen = pp->lencode ;
  637. }
  638. switch ( up->linecount ) {
  639. case 1 : /* JYYMMDD HHMMSSS */
  640. if ( iLen != 15 ) {
  641. #ifdef DEBUG
  642. if ( debug >= 2 ) {
  643. printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
  644. }
  645. #endif
  646. up->lineerror = 1 ;
  647. break ;
  648. }
  649. rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
  650. &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
  651. if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
  652. || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
  653. #ifdef DEBUG
  654. if ( debug >= 2 ) {
  655. printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n", sFunctionName,
  656. rc, up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond ) ;
  657. }
  658. #endif
  659. up->lineerror = 1 ;
  660. break ;
  661. }
  662. up->year += 2000 ;
  663. up->msecond *= 100 ;
  664. break ;
  665. default : /* Unexpected reply */
  666. up->lineerror = 1 ;
  667. break ;
  668. }
  669. return 1 ;
  670. }
  671. /**************************************************************************************************/
  672. static int
  673. jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
  674. {
  675. static char *sFunctionName = "jjy_receive_echokeisokuki_lt2000" ;
  676. struct jjyunit *up ;
  677. struct refclockproc *pp ;
  678. struct peer *peer;
  679. char *pBuf ;
  680. int iLen ;
  681. int rc ;
  682. int i, ibcc, ibcc1, ibcc2 ;
  683. /*
  684. * Initialize pointers and read the timecode and timestamp
  685. */
  686. peer = (struct peer *) rbufp->recv_srcclock ;
  687. pp = peer->procptr ;
  688. up = (struct jjyunit *) pp->unitptr ;
  689. if ( up->linediscipline == LDISC_RAW ) {
  690. pBuf = up->rawbuf ;
  691. iLen = up->charcount ;
  692. } else {
  693. pBuf = pp->a_lastcode ;
  694. iLen = pp->lencode ;
  695. }
  696. switch ( up->linecount ) {
  697. case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
  698. if ( ( up->operationmode == 1 && iLen != 15 ) || ( up->operationmode == 2 && iLen != 17 ) ) {
  699. #ifdef DEBUG
  700. if ( debug >= 2 ) {
  701. printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
  702. }
  703. #endif
  704. if ( up->operationmode == 1 ) {
  705. #ifdef DEBUG
  706. if ( debug ) {
  707. printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
  708. }
  709. #endif
  710. if ( write ( pp->io.fd, "#",1 ) != 1 ) {
  711. refclock_report ( peer, CEVNT_FAULT ) ;
  712. }
  713. }
  714. up->lineerror = 1 ;
  715. break ;
  716. }
  717. if ( up->operationmode == 1 ) {
  718. for ( i = ibcc = 0 ; i < 13 ; i ++ ) ibcc ^= pBuf[i] ;
  719. ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
  720. ibcc2 = 0x30 | ( ( ibcc ) & 0xF ) ;
  721. if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
  722. #ifdef DEBUG
  723. if ( debug >= 2 ) {
  724. printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n", sFunctionName, pBuf[13]&0xFF, pBuf[14]&0xFF, ibcc1, ibcc2 ) ;
  725. }
  726. #endif
  727. up->lineerror = 1 ;
  728. break ;
  729. }
  730. }
  731. rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
  732. &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second ) ;
  733. if ( rc != 6 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
  734. || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
  735. #ifdef DEBUG
  736. if ( debug >= 2 ) {
  737. printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n", sFunctionName,
  738. rc, up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
  739. }
  740. #endif
  741. up->lineerror = 1 ;
  742. break ;
  743. }
  744. up->year += 2000 ;
  745. if ( up->operationmode == 2 ) {
  746. /* A time stamp comes on every 0.5 seccond in the mode 2 of the LT-2000. */
  747. up->msecond = 500 ;
  748. pp->second -- ;
  749. if ( pp->second < 0 ) {
  750. pp->second = 59 ;
  751. pp->minute -- ;
  752. if ( pp->minute < 0 ) {
  753. pp->minute = 59 ;
  754. pp->hour -- ;
  755. if ( pp->hour < 0 ) {
  756. pp->hour = 23 ;
  757. pp->day -- ;
  758. if ( pp->day < 1 ) {
  759. pp->year -- ;
  760. pp->day = ymd2yd ( pp->year, 12, 31 ) ;
  761. }
  762. }
  763. }
  764. }
  765. /* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
  766. #ifdef DEBUG
  767. if ( debug ) {
  768. printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
  769. }
  770. #endif
  771. if ( write ( pp->io.fd, "#",1 ) != 1 ) {
  772. refclock_report ( peer, CEVNT_FAULT ) ;
  773. }
  774. }
  775. break ;
  776. default : /* Unexpected reply */
  777. #ifdef DEBUG
  778. if ( debug ) {
  779. printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
  780. }
  781. #endif
  782. if ( write ( pp->io.fd, "#",1 ) != 1 ) {
  783. refclock_report ( peer, CEVNT_FAULT ) ;
  784. }
  785. up->lineerror = 1 ;
  786. break ;
  787. }
  788. return 1 ;
  789. }
  790. /**************************************************************************************************/
  791. static int
  792. jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
  793. {
  794. static char *sFunctionName = "jjy_receive_citizentic_jjy200" ;
  795. struct jjyunit *up ;
  796. struct refclockproc *pp ;
  797. struct peer *peer;
  798. char *pBuf ;
  799. int iLen ;
  800. int rc ;
  801. char cApostrophe, sStatus[3] ;
  802. int iWeekday ;
  803. /*
  804. * Initialize pointers and read the timecode and timestamp
  805. */
  806. peer = (struct peer *) rbufp->recv_srcclock ;
  807. pp = peer->procptr ;
  808. up = (struct jjyunit *) pp->unitptr ;
  809. if ( up->linediscipline == LDISC_RAW ) {
  810. pBuf = up->rawbuf ;
  811. iLen = up->charcount ;
  812. } else {
  813. pBuf = pp->a_lastcode ;
  814. iLen = pp->lencode ;
  815. }
  816. /*
  817. * JJY-200 sends a timestamp every second.
  818. * So, a timestamp is ignored unless it is right after polled.
  819. */
  820. if ( ! up->bPollFlag ) return 0 ;
  821. switch ( up->linecount ) {
  822. case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
  823. if ( iLen != 23 ) {
  824. #ifdef DEBUG
  825. if ( debug >= 2 ) {
  826. printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
  827. }
  828. #endif
  829. up->lineerror = 1 ;
  830. break ;
  831. }
  832. rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
  833. &cApostrophe, sStatus,
  834. &up->year, &up->month, &up->day, &iWeekday, &up->hour, &up->minute, &up->second ) ;
  835. sStatus[2] = 0 ;
  836. if ( rc != 9 || cApostrophe != '\'' || strcmp( sStatus, "OK" ) != 0
  837. || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
  838. || iWeekday > 6
  839. || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
  840. #ifdef DEBUG
  841. if ( debug >= 2 ) {
  842. printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n", sFunctionName,
  843. rc, cApostrophe, sStatus, up->year, up->month, up->day, iWeekday, up->hour, up->minute, up->second ) ;
  844. }
  845. #endif
  846. up->lineerror = 1 ;
  847. break ;
  848. }
  849. up->year += 2000 ;
  850. up->msecond = 0 ;
  851. break ;
  852. default : /* Unexpected reply */
  853. up->lineerror = 1 ;
  854. break ;
  855. }
  856. return 1 ;
  857. }
  858. /**************************************************************************************************/
  859. /* jjy_poll - called by the transmit procedure */
  860. /**************************************************************************************************/
  861. static void
  862. jjy_poll ( int unit, struct peer *peer )
  863. {
  864. struct jjyunit *up;
  865. struct refclockproc *pp;
  866. pp = peer->procptr;
  867. up = (struct jjyunit *) pp->unitptr ;
  868. if ( pp->polls > 0 && up->linecount == 0 ) {
  869. /*
  870. * No reply for last command
  871. */
  872. refclock_report ( peer, CEVNT_TIMEOUT ) ;
  873. }
  874. #ifdef DEBUG
  875. if ( debug ) {
  876. printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
  877. }
  878. #endif
  879. pp->polls ++ ;
  880. up->bPollFlag = 1 ;
  881. up->linecount = 0 ;
  882. up->lineerror = 0 ;
  883. up->charcount = 0 ;
  884. switch ( up->unittype ) {
  885. case UNITTYPE_TRISTATE_JJY01 :
  886. jjy_poll_tristate_jjy01 ( unit, peer ) ;
  887. break ;
  888. case UNITTYPE_CDEX_JST2000 :
  889. jjy_poll_cdex_jst2000 ( unit, peer ) ;
  890. break ;
  891. case UNITTYPE_ECHOKEISOKUKI_LT2000 :
  892. jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
  893. break ;
  894. case UNITTYPE_CITIZENTIC_JJY200 :
  895. jjy_poll_citizentic_jjy200 ( unit, peer ) ;
  896. break ;
  897. default :
  898. break ;
  899. }
  900. }
  901. /**************************************************************************************************/
  902. static void
  903. jjy_poll_tristate_jjy01 ( int unit, struct peer *peer )
  904. {
  905. struct refclockproc *pp;
  906. pp = peer->procptr;
  907. /*
  908. * Send "date<CR><LF>" command
  909. */
  910. #ifdef DEBUG
  911. if ( debug ) {
  912. printf ( "jjy_poll_tristate_jjy01 (refclock_jjy.c) : send 'date<CR><LF>'\n" ) ;
  913. }
  914. #endif
  915. if ( write ( pp->io.fd, "date\r\n",6 ) != 6 ) {
  916. refclock_report ( peer, CEVNT_FAULT ) ;
  917. }
  918. }
  919. /**************************************************************************************************/
  920. static void
  921. jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
  922. {
  923. struct refclockproc *pp;
  924. pp = peer->procptr;
  925. /*
  926. * Send "<ENQ>1J<ETX>" command
  927. */
  928. #ifdef DEBUG
  929. if ( debug ) {
  930. printf ( "jjy_poll_cdex_jst2000 (refclock_jjy.c) : send '<ENQ>1J<ETX>'\n" ) ;
  931. }
  932. #endif
  933. if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) {
  934. refclock_report ( peer, CEVNT_FAULT ) ;
  935. }
  936. }
  937. /**************************************************************************************************/
  938. static void
  939. jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
  940. {
  941. struct jjyunit *up;
  942. struct refclockproc *pp;
  943. char sCmd[2] ;
  944. pp = peer->procptr;
  945. up = (struct jjyunit *) pp->unitptr ;
  946. /*
  947. * Send "T" or "C" command
  948. */
  949. switch ( up->operationmode ) {
  950. case 1 : sCmd[0] = 'T' ; break ;
  951. case 2 : sCmd[0] = 'C' ; break ;
  952. }
  953. sCmd[1] = 0 ;
  954. #ifdef DEBUG
  955. if ( debug ) {
  956. printf ( "jjy_poll_echokeisokuki_lt2000 (refclock_jjy.c) : send '%s'\n", sCmd ) ;
  957. }
  958. #endif
  959. if ( write ( pp->io.fd, sCmd, 1 ) != 1 ) {
  960. refclock_report ( peer, CEVNT_FAULT ) ;
  961. }
  962. }
  963. /**************************************************************************************************/
  964. static void
  965. jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
  966. {
  967. /* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
  968. }
  969. #else
  970. int refclock_jjy_bs ;
  971. #endif /* REFCLOCK */