Annotation of embedaddon/ntp/ntpd/refclock_jjy.c, revision 1.1.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>