1106163Sroberto/* 2106163Sroberto * refclock_jjy - clock driver for JJY receivers 3106163Sroberto */ 4106163Sroberto 5106163Sroberto/**********************************************************************/ 6285612Sdelphij/* */ 7285612Sdelphij/* Copyright (C) 2001-2015, Takao Abe. All rights reserved. */ 8285612Sdelphij/* */ 9106163Sroberto/* Permission to use, copy, modify, and distribute this software */ 10285612Sdelphij/* and its documentation for any purpose is hereby granted */ 11106163Sroberto/* without fee, provided that the following conditions are met: */ 12285612Sdelphij/* */ 13106163Sroberto/* One retains the entire copyright notice properly, and both the */ 14106163Sroberto/* copyright notice and this license. in the documentation and/or */ 15285612Sdelphij/* other materials provided with the distribution. */ 16285612Sdelphij/* */ 17106163Sroberto/* This software and the name of the author must not be used to */ 18106163Sroberto/* endorse or promote products derived from this software without */ 19285612Sdelphij/* prior written permission. */ 20285612Sdelphij/* */ 21106163Sroberto/* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED */ 22285612Sdelphij/* WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE */ 23285612Sdelphij/* IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A */ 24285612Sdelphij/* PARTICULAR PURPOSE. */ 25106163Sroberto/* IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT, */ 26106163Sroberto/* INDIRECT, GENERAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 27285612Sdelphij/* ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */ 28106163Sroberto/* GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS */ 29106163Sroberto/* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */ 30285612Sdelphij/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ( INCLUDING */ 31106163Sroberto/* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF */ 32106163Sroberto/* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 33285612Sdelphij/* */ 34106163Sroberto/* This driver is developed in my private time, and is opened as */ 35285612Sdelphij/* voluntary contributions for the NTP. */ 36106163Sroberto/* The manufacturer of the JJY receiver has not participated in */ 37285612Sdelphij/* a development of this driver. */ 38106163Sroberto/* The manufacturer does not warrant anything about this driver, */ 39285612Sdelphij/* and is not liable for anything about this driver. */ 40285612Sdelphij/* */ 41106163Sroberto/**********************************************************************/ 42285612Sdelphij/* */ 43285612Sdelphij/* Author Takao Abe */ 44285612Sdelphij/* Email takao_abe@xurb.jp */ 45285612Sdelphij/* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */ 46285612Sdelphij/* */ 47285612Sdelphij/* The email address abetakao@bea.hi-ho.ne.jp is never read */ 48285612Sdelphij/* from 2010, because a few filtering rule are provided by the */ 49285612Sdelphij/* "hi-ho.ne.jp", and lots of spam mail are reached. */ 50285612Sdelphij/* New email address for supporting the refclock_jjy is */ 51285612Sdelphij/* takao_abe@xurb.jp */ 52285612Sdelphij/* */ 53106163Sroberto/**********************************************************************/ 54285612Sdelphij/* */ 55285612Sdelphij/* History */ 56285612Sdelphij/* */ 57285612Sdelphij/* 2001/07/15 */ 58285612Sdelphij/* [New] Support the Tristate Ltd. JJY receiver */ 59285612Sdelphij/* */ 60285612Sdelphij/* 2001/08/04 */ 61285612Sdelphij/* [Change] Log to clockstats even if bad reply */ 62285612Sdelphij/* [Fix] PRECISION = (-3) (about 100 ms) */ 63285612Sdelphij/* [Add] Support the C-DEX Co.Ltd. JJY receiver */ 64285612Sdelphij/* */ 65285612Sdelphij/* 2001/12/04 */ 66106163Sroberto/* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */ 67285612Sdelphij/* */ 68285612Sdelphij/* 2002/07/12 */ 69285612Sdelphij/* [Fix] Portability for FreeBSD ( patched by the user ) */ 70285612Sdelphij/* */ 71285612Sdelphij/* 2004/10/31 */ 72182007Sroberto/* [Change] Command send timing for the Tristate Ltd. JJY receiver */ 73285612Sdelphij/* JJY-01 ( Firmware version 2.01 ) */ 74285612Sdelphij/* Thanks to Andy Taki for testing under FreeBSD */ 75285612Sdelphij/* */ 76285612Sdelphij/* 2004/11/28 */ 77285612Sdelphij/* [Add] Support the Echo Keisokuki LT-2000 receiver */ 78285612Sdelphij/* */ 79285612Sdelphij/* 2006/11/04 */ 80285612Sdelphij/* [Fix] C-DEX JST2000 */ 81285612Sdelphij/* Thanks to Hideo Kuramatsu for the patch */ 82285612Sdelphij/* */ 83285612Sdelphij/* 2009/04/05 */ 84285612Sdelphij/* [Add] Support the CITIZEN T.I.C JJY-200 receiver */ 85285612Sdelphij/* */ 86285612Sdelphij/* 2010/11/20 */ 87285612Sdelphij/* [Change] Bug 1618 ( Harmless ) */ 88285612Sdelphij/* Code clean up ( Remove unreachable codes ) in */ 89285612Sdelphij/* jjy_start() */ 90285612Sdelphij/* [Change] Change clockstats format of the Tristate JJY01/02 */ 91285612Sdelphij/* Issues more command to get the status of the receiver */ 92285612Sdelphij/* when "fudge 127.127.40.X flag1 1" is specified */ 93285612Sdelphij/* ( DATE,STIM -> DCST,STUS,DATE,STIM ) */ 94285612Sdelphij/* */ 95285612Sdelphij/* 2011/04/30 */ 96285612Sdelphij/* [Add] Support the Tristate Ltd. TS-GPSclock-01 */ 97285612Sdelphij/* */ 98285612Sdelphij/* 2015/03/29 */ 99285612Sdelphij/* [Add] Support the Telephone JJY */ 100285612Sdelphij/* [Change] Split the start up routine into each JJY receivers. */ 101285612Sdelphij/* Change raw data internal bufferring process */ 102285612Sdelphij/* Change over midnight handling of TS-JJY01 and TS-GPS01 */ 103285612Sdelphij/* to put DATE command between before and after TIME's. */ 104285612Sdelphij/* Unify the writing clockstats of all JJY receivers. */ 105285612Sdelphij/* */ 106285612Sdelphij/* 2015/05/15 */ 107285612Sdelphij/* [Add] Support the SEIKO TIME SYSTEMS TDC-300 */ 108285612Sdelphij/* */ 109310419Sdelphij/* 2016/05/08 */ 110310419Sdelphij/* [Fix] C-DEX JST2000 */ 111310419Sdelphij/* Thanks to Mr. Kuramatsu for the report and the patch. */ 112310419Sdelphij/* */ 113330567Sgordon/* 2017/04/30 */ 114330567Sgordon/* [Change] Avoid a wrong report of the coverity static analysis */ 115330567Sgordon/* tool. ( The code is harmless and has no bug. ) */ 116330567Sgordon/* teljjy_conn_send() */ 117330567Sgordon/* */ 118106163Sroberto/**********************************************************************/ 119106163Sroberto 120106163Sroberto#ifdef HAVE_CONFIG_H 121106163Sroberto#include <config.h> 122106163Sroberto#endif 123106163Sroberto 124106163Sroberto#if defined(REFCLOCK) && defined(CLOCK_JJY) 125106163Sroberto 126106163Sroberto#include <stdio.h> 127106163Sroberto#include <ctype.h> 128106163Sroberto#include <string.h> 129106163Sroberto#include <sys/time.h> 130106163Sroberto#include <time.h> 131106163Sroberto 132106163Sroberto#include "ntpd.h" 133106163Sroberto#include "ntp_io.h" 134106163Sroberto#include "ntp_tty.h" 135106163Sroberto#include "ntp_refclock.h" 136106163Sroberto#include "ntp_calendar.h" 137106163Sroberto#include "ntp_stdlib.h" 138106163Sroberto 139106163Sroberto/**********************************************************************/ 140106163Sroberto 141106163Sroberto/* 142106163Sroberto * Interface definitions 143106163Sroberto */ 144285612Sdelphij#define DEVICE "/dev/jjy%d" /* device name and unit */ 145285612Sdelphij#define SPEED232_TRISTATE_JJY01 B9600 /* UART speed (9600 baud) */ 146285612Sdelphij#define SPEED232_CDEX_JST2000 B9600 /* UART speed (9600 baud) */ 147285612Sdelphij#define SPEED232_ECHOKEISOKUKI_LT2000 B9600 /* UART speed (9600 baud) */ 148285612Sdelphij#define SPEED232_CITIZENTIC_JJY200 B4800 /* UART speed (4800 baud) */ 149285612Sdelphij#define SPEED232_TRISTATE_GPSCLOCK01 B38400 /* USB speed (38400 baud) */ 150285612Sdelphij#define SPEED232_SEIKO_TIMESYS_TDC_300 B2400 /* UART speed (2400 baud) */ 151285612Sdelphij#define SPEED232_TELEPHONE B2400 /* UART speed (4800 baud) */ 152285612Sdelphij#define REFID "JJY" /* reference ID */ 153106163Sroberto#define DESCRIPTION "JJY Receiver" 154285612Sdelphij#define PRECISION (-3) /* precision assumed (about 100 ms) */ 155106163Sroberto 156106163Sroberto/* 157106163Sroberto * JJY unit control structure 158106163Sroberto */ 159285612Sdelphij 160285612Sdelphijstruct jjyRawDataBreak { 161294569Sdelphij const char * pString ; 162294569Sdelphij int iLength ; 163285612Sdelphij} ; 164285612Sdelphij 165285612Sdelphij#define MAX_TIMESTAMP 6 166285612Sdelphij#define MAX_RAWBUF 100 167285612Sdelphij#define MAX_LOOPBACK 5 168285612Sdelphij 169106163Srobertostruct jjyunit { 170285612Sdelphij/* Set up by the function "jjy_start_xxxxxxxx" */ 171285612Sdelphij char unittype ; /* UNITTYPE_XXXXXXXXXX */ 172285612Sdelphij short operationmode ; /* Echo Keisokuki LT-2000 */ 173285612Sdelphij int linespeed ; /* SPEED232_XXXXXXXXXX */ 174285612Sdelphij short linediscipline ; /* LDISC_CLK or LDISC_RAW */ 175285612Sdelphij/* Receiving data */ 176285612Sdelphij char bInitError ; /* Set by jjy_start if any error during initialization */ 177285612Sdelphij short iProcessState ; /* JJY_PROCESS_STATE_XXXXXX */ 178285612Sdelphij char bReceiveFlag ; /* Set and reset by jjy_receive */ 179285612Sdelphij char bLineError ; /* Reset by jjy_poll / Set by jjy_receive_xxxxxxxx*/ 180285612Sdelphij short iCommandSeq ; /* 0:Idle Non-Zero:Issued */ 181285612Sdelphij short iReceiveSeq ; 182285612Sdelphij int iLineCount ; 183106163Sroberto int year, month, day, hour, minute, second, msecond ; 184285612Sdelphij int leapsecond ; 185285612Sdelphij int iTimestampCount ; /* TS-JJY01, TS-GPS01, Telephone-JJY */ 186285612Sdelphij int iTimestamp [ MAX_TIMESTAMP ] ; /* Serial second ( 0 - 86399 ) */ 187106163Sroberto/* LDISC_RAW only */ 188285612Sdelphij char sRawBuf [ MAX_RAWBUF ] ; 189285612Sdelphij int iRawBufLen ; 190285612Sdelphij struct jjyRawDataBreak *pRawBreak ; 191285612Sdelphij char bWaitBreakString ; 192285612Sdelphij char sLineBuf [ MAX_RAWBUF ] ; 193285612Sdelphij int iLineBufLen ; 194285612Sdelphij char sTextBuf [ MAX_RAWBUF ] ; 195285612Sdelphij int iTextBufLen ; 196285612Sdelphij char bSkipCntrlCharOnly ; 197285612Sdelphij/* Telephone JJY auto measurement of the loopback delay */ 198285612Sdelphij char bLoopbackMode ; 199285612Sdelphij short iLoopbackCount ; 200285612Sdelphij struct timeval sendTime[MAX_LOOPBACK], delayTime[MAX_LOOPBACK] ; 201285612Sdelphij char bLoopbackTimeout[MAX_LOOPBACK] ; 202285612Sdelphij short iLoopbackValidCount ; 203285612Sdelphij/* Telephone JJY timer */ 204285612Sdelphij short iTeljjySilentTimer ; 205285612Sdelphij short iTeljjyStateTimer ; 206285612Sdelphij/* Telephone JJY control finite state machine */ 207285612Sdelphij short iClockState ; 208285612Sdelphij short iClockEvent ; 209285612Sdelphij short iClockCommandSeq ; 210285612Sdelphij/* Modem timer */ 211285612Sdelphij short iModemSilentCount ; 212285612Sdelphij short iModemSilentTimer ; 213285612Sdelphij short iModemStateTimer ; 214285612Sdelphij/* Modem control finite state machine */ 215285612Sdelphij short iModemState ; 216285612Sdelphij short iModemEvent ; 217285612Sdelphij short iModemCommandSeq ; 218106163Sroberto}; 219106163Sroberto 220285612Sdelphij#define UNITTYPE_TRISTATE_JJY01 1 221285612Sdelphij#define UNITTYPE_CDEX_JST2000 2 222182007Sroberto#define UNITTYPE_ECHOKEISOKUKI_LT2000 3 223200576Sroberto#define UNITTYPE_CITIZENTIC_JJY200 4 224285612Sdelphij#define UNITTYPE_TRISTATE_GPSCLOCK01 5 225285612Sdelphij#define UNITTYPE_SEIKO_TIMESYS_TDC_300 6 226285612Sdelphij#define UNITTYPE_TELEPHONE 100 227106163Sroberto 228285612Sdelphij#define JJY_PROCESS_STATE_IDLE 0 229285612Sdelphij#define JJY_PROCESS_STATE_POLL 1 230285612Sdelphij#define JJY_PROCESS_STATE_RECEIVE 2 231285612Sdelphij#define JJY_PROCESS_STATE_DONE 3 232285612Sdelphij#define JJY_PROCESS_STATE_ERROR 4 233285612Sdelphij 234285612Sdelphij/**********************************************************************/ 235285612Sdelphij 236106163Sroberto/* 237285612Sdelphij * Function calling structure 238285612Sdelphij * 239285612Sdelphij * jjy_start 240285612Sdelphij * |-- jjy_start_tristate_jjy01 241285612Sdelphij * |-- jjy_start_cdex_jst2000 242285612Sdelphij * |-- jjy_start_echokeisokuki_lt2000 243285612Sdelphij * |-- jjy_start_citizentic_jjy200 244285612Sdelphij * |-- jjy_start_tristate_gpsclock01 245285612Sdelphij * |-- jjy_start_seiko_tsys_tdc_300 246285612Sdelphij * |-- jjy_start_telephone 247285612Sdelphij * 248285612Sdelphij * jjy_shutdown 249285612Sdelphij * 250285612Sdelphij * jjy_poll 251285612Sdelphij * |-- jjy_poll_tristate_jjy01 252285612Sdelphij * |-- jjy_poll_cdex_jst2000 253285612Sdelphij * |-- jjy_poll_echokeisokuki_lt2000 254285612Sdelphij * |-- jjy_poll_citizentic_jjy200 255285612Sdelphij * |-- jjy_poll_tristate_gpsclock01 256285612Sdelphij * |-- jjy_poll_seiko_tsys_tdc_300 257285612Sdelphij * |-- jjy_poll_telephone 258285612Sdelphij * |-- teljjy_control 259285612Sdelphij * |-- teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 260285612Sdelphij * |-- modem_connect 261285612Sdelphij * |-- modem_control 262285612Sdelphij * |-- modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 263285612Sdelphij * 264285612Sdelphij * jjy_receive 265285612Sdelphij * | 266285612Sdelphij * |-- jjy_receive_tristate_jjy01 267285612Sdelphij * | |-- jjy_synctime 268285612Sdelphij * |-- jjy_receive_cdex_jst2000 269285612Sdelphij * | |-- jjy_synctime 270285612Sdelphij * |-- jjy_receive_echokeisokuki_lt2000 271285612Sdelphij * | |-- jjy_synctime 272285612Sdelphij * |-- jjy_receive_citizentic_jjy200 273285612Sdelphij * | |-- jjy_synctime 274285612Sdelphij * |-- jjy_receive_tristate_gpsclock01 275285612Sdelphij * | |-- jjy_synctime 276285612Sdelphij * |-- jjy_receive_seiko_tsys_tdc_300 277285612Sdelphij * | |-- jjy_synctime 278285612Sdelphij * |-- jjy_receive_telephone 279285612Sdelphij * |-- modem_receive 280285612Sdelphij * | |-- modem_control 281285612Sdelphij * | |-- modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 282285612Sdelphij * |-- teljjy_control 283285612Sdelphij * |-- teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 284285612Sdelphij * |-- jjy_synctime 285285612Sdelphij * |-- modem_disconnect 286285612Sdelphij * |-- modem_control 287285612Sdelphij * |-- modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 288285612Sdelphij * 289285612Sdelphij * jjy_timer 290285612Sdelphij * |-- jjy_timer_telephone 291285612Sdelphij * |-- modem_timer 292285612Sdelphij * | |-- modem_control 293285612Sdelphij * | |-- modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 294285612Sdelphij * |-- teljjy_control 295285612Sdelphij * |-- teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 296285612Sdelphij * |-- modem_disconnect 297285612Sdelphij * |-- modem_control 298285612Sdelphij * |-- modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. ) 299285612Sdelphij * 300106163Sroberto * Function prototypes 301106163Sroberto */ 302106163Sroberto 303285612Sdelphijstatic int jjy_start (int, struct peer *); 304285612Sdelphijstatic int jjy_start_tristate_jjy01 (int, struct peer *, struct jjyunit *); 305285612Sdelphijstatic int jjy_start_cdex_jst2000 (int, struct peer *, struct jjyunit *); 306285612Sdelphijstatic int jjy_start_echokeisokuki_lt2000 (int, struct peer *, struct jjyunit *); 307285612Sdelphijstatic int jjy_start_citizentic_jjy200 (int, struct peer *, struct jjyunit *); 308285612Sdelphijstatic int jjy_start_tristate_gpsclock01 (int, struct peer *, struct jjyunit *); 309285612Sdelphijstatic int jjy_start_seiko_tsys_tdc_300 (int, struct peer *, struct jjyunit *); 310285612Sdelphijstatic int jjy_start_telephone (int, struct peer *, struct jjyunit *); 311285612Sdelphij 312285612Sdelphijstatic void jjy_shutdown (int, struct peer *); 313285612Sdelphij 314285612Sdelphijstatic void jjy_poll (int, struct peer *); 315285612Sdelphijstatic void jjy_poll_tristate_jjy01 (int, struct peer *); 316285612Sdelphijstatic void jjy_poll_cdex_jst2000 (int, struct peer *); 317285612Sdelphijstatic void jjy_poll_echokeisokuki_lt2000 (int, struct peer *); 318285612Sdelphijstatic void jjy_poll_citizentic_jjy200 (int, struct peer *); 319285612Sdelphijstatic void jjy_poll_tristate_gpsclock01 (int, struct peer *); 320285612Sdelphijstatic void jjy_poll_seiko_tsys_tdc_300 (int, struct peer *); 321285612Sdelphijstatic void jjy_poll_telephone (int, struct peer *); 322285612Sdelphij 323285612Sdelphijstatic void jjy_receive (struct recvbuf *); 324285612Sdelphijstatic int jjy_receive_tristate_jjy01 (struct recvbuf *); 325285612Sdelphijstatic int jjy_receive_cdex_jst2000 (struct recvbuf *); 326285612Sdelphijstatic int jjy_receive_echokeisokuki_lt2000 (struct recvbuf *); 327285612Sdelphijstatic int jjy_receive_citizentic_jjy200 (struct recvbuf *); 328285612Sdelphijstatic int jjy_receive_tristate_gpsclock01 (struct recvbuf *); 329285612Sdelphijstatic int jjy_receive_seiko_tsys_tdc_300 (struct recvbuf *); 330285612Sdelphijstatic int jjy_receive_telephone (struct recvbuf *); 331285612Sdelphij 332285612Sdelphijstatic void jjy_timer (int, struct peer *); 333285612Sdelphijstatic void jjy_timer_telephone (int, struct peer *); 334285612Sdelphij 335285612Sdelphijstatic void jjy_synctime ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 336285612Sdelphijstatic void jjy_write_clockstats ( struct peer *, int, const char* ) ; 337285612Sdelphij 338285612Sdelphijstatic int getRawDataBreakPosition ( struct jjyunit *, int ) ; 339285612Sdelphij 340285612Sdelphijstatic short getModemState ( struct jjyunit * ) ; 341285612Sdelphijstatic int isModemStateConnect ( short ) ; 342285612Sdelphijstatic int isModemStateDisconnect ( short ) ; 343285612Sdelphijstatic int isModemStateTimerOn ( struct jjyunit * ) ; 344285612Sdelphijstatic void modem_connect ( int, struct peer * ) ; 345285612Sdelphijstatic void modem_disconnect ( int, struct peer * ) ; 346285612Sdelphijstatic int modem_receive ( struct recvbuf * ) ; 347285612Sdelphijstatic void modem_timer ( int, struct peer * ); 348285612Sdelphij 349285612Sdelphijstatic void printableString ( char*, int, const char*, int ) ; 350285612Sdelphij 351106163Sroberto/* 352106163Sroberto * Transfer vector 353106163Sroberto */ 354106163Srobertostruct refclock refclock_jjy = { 355285612Sdelphij jjy_start, /* start up driver */ 356285612Sdelphij jjy_shutdown, /* shutdown driver */ 357285612Sdelphij jjy_poll, /* transmit poll message */ 358285612Sdelphij noentry, /* not used */ 359285612Sdelphij noentry, /* not used */ 360285612Sdelphij noentry, /* not used */ 361285612Sdelphij jjy_timer /* 1 second interval timer */ 362106163Sroberto}; 363106163Sroberto 364106163Sroberto/* 365106163Sroberto * Start up driver return code 366106163Sroberto */ 367106163Sroberto#define RC_START_SUCCESS 1 368285612Sdelphij#define RC_START_ERROR 0 369106163Sroberto 370106163Sroberto/* 371106163Sroberto * Local constants definition 372106163Sroberto */ 373106163Sroberto 374285612Sdelphij#define MAX_LOGTEXT 100 375106163Sroberto 376285612Sdelphij#ifndef TRUE 377285612Sdelphij#define TRUE (0==0) 378285612Sdelphij#endif 379285612Sdelphij#ifndef FALSE 380285612Sdelphij#define FALSE (!TRUE) 381285612Sdelphij#endif 382106163Sroberto 383285612Sdelphij/* Local constants definition for the return code of the jjy_receive_xxxxxxxx */ 384285612Sdelphij 385285612Sdelphij#define JJY_RECEIVE_DONE 0 386285612Sdelphij#define JJY_RECEIVE_SKIP 1 387285612Sdelphij#define JJY_RECEIVE_UNPROCESS 2 388285612Sdelphij#define JJY_RECEIVE_WAIT 3 389285612Sdelphij#define JJY_RECEIVE_ERROR 4 390285612Sdelphij 391285612Sdelphij/* Local constants definition for the 2nd parameter of the jjy_write_clockstats */ 392285612Sdelphij 393285612Sdelphij#define JJY_CLOCKSTATS_MARK_NONE 0 394285612Sdelphij#define JJY_CLOCKSTATS_MARK_JJY 1 395285612Sdelphij#define JJY_CLOCKSTATS_MARK_SEND 2 396285612Sdelphij#define JJY_CLOCKSTATS_MARK_RECEIVE 3 397285612Sdelphij#define JJY_CLOCKSTATS_MARK_INFORMATION 4 398285612Sdelphij#define JJY_CLOCKSTATS_MARK_ATTENTION 5 399285612Sdelphij#define JJY_CLOCKSTATS_MARK_WARNING 6 400285612Sdelphij#define JJY_CLOCKSTATS_MARK_ERROR 7 401330567Sgordon#define JJY_CLOCKSTATS_MARK_BUG 8 402285612Sdelphij 403285612Sdelphij/* Local constants definition for the clockstats messages */ 404285612Sdelphij 405285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_ECHOBACK "* Echoback" 406285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_IGNORE_REPLY "* Ignore replay : [%s]" 407285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2 "* Over midnight : timestamp=%d, %d" 408285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_3 "* Over midnight : timestamp=%d, %d, %d" 409285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_TIMESTAMP_UNSURE "* Unsure timestamp : %s" 410285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_LOOPBACK_DELAY "* Loopback delay : %d.%03d mSec." 411285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_DELAY_ADJUST "* Delay adjustment : %d mSec. ( valid=%hd/%d )" 412285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_DELAY_UNADJUST "* Delay adjustment : None ( valid=%hd/%d )" 413285612Sdelphij 414285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY "# Unexpected reply : [%s]" 415285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH "# Invalid length : length=%d" 416285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY "# Too many reply : count=%d" 417285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY "# Invalid reply : [%s]" 418285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2 "# Slow reply : timestamp=%d, %d" 419285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_3 "# Slow reply : timestamp=%d, %d, %d" 420285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE "# Invalid date : rc=%d year=%d month=%d day=%d" 421285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME "# Invalid time : rc=%d hour=%d minute=%d second=%d" 422285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME "# Invalid time : rc=%d year=%d month=%d day=%d hour=%d minute=%d second=%d" 423285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_LEAP "# Invalid leap : leapsecond=[%s]" 424285612Sdelphij#define JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_STATUS "# Invalid status : status=[%s]" 425285612Sdelphij 426285612Sdelphij/* Debug print macro */ 427285612Sdelphij 428285612Sdelphij#ifdef DEBUG 429285612Sdelphij#define DEBUG_PRINTF_JJY_RECEIVE(sFunc,iLen) { if ( debug ) { printf ( "refclock_jjy.c : %s : iProcessState=%d bLineError=%d iCommandSeq=%d iLineCount=%d iTimestampCount=%d iLen=%d\n", sFunc, up->iProcessState, up->bLineError, up->iCommandSeq, up->iLineCount, up->iTimestampCount, iLen ) ; } } 430285612Sdelphij#else 431285612Sdelphij#define DEBUG_PRINTF_JJY_RECEIVE(sFunc,iLen) 432285612Sdelphij#endif 433285612Sdelphij 434106163Sroberto/**************************************************************************************************/ 435106163Sroberto/* jjy_start - open the devices and initialize data for processing */ 436106163Sroberto/**************************************************************************************************/ 437106163Srobertostatic int 438106163Srobertojjy_start ( int unit, struct peer *peer ) 439106163Sroberto{ 440106163Sroberto 441285612Sdelphij struct refclockproc *pp ; 442285612Sdelphij struct jjyunit *up ; 443285612Sdelphij int rc ; 444106163Sroberto int fd ; 445285612Sdelphij char sDeviceName [ sizeof(DEVICE) + 10 ], sLog [ 60 ] ; 446106163Sroberto 447106163Sroberto#ifdef DEBUG 448106163Sroberto if ( debug ) { 449285612Sdelphij printf( "refclock_jjy.c : jjy_start : %s mode=%d dev=%s unit=%d\n", 450285612Sdelphij ntoa(&peer->srcadr), peer->ttl, DEVICE, unit ) ; 451106163Sroberto } 452106163Sroberto#endif 453106163Sroberto 454285612Sdelphij /* Allocate memory for the unit structure */ 455285612Sdelphij up = emalloc( sizeof(*up) ) ; 456285612Sdelphij if ( up == NULL ) { 457285612Sdelphij msyslog ( LOG_ERR, "refclock_jjy.c : jjy_start : emalloc" ) ; 458106163Sroberto return RC_START_ERROR ; 459106163Sroberto } 460285612Sdelphij memset ( up, 0, sizeof(*up) ) ; 461106163Sroberto 462285612Sdelphij up->bInitError = FALSE ; 463285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_IDLE ; 464285612Sdelphij up->bReceiveFlag = FALSE ; 465285612Sdelphij up->iCommandSeq = 0 ; 466285612Sdelphij up->iLineCount = 0 ; 467285612Sdelphij up->iTimestampCount = 0 ; 468285612Sdelphij up->bWaitBreakString = FALSE ; 469285612Sdelphij up->iRawBufLen = up->iLineBufLen = up->iTextBufLen = 0 ; 470285612Sdelphij up->bSkipCntrlCharOnly = TRUE ; 471106163Sroberto 472285612Sdelphij /* Set up the device name */ 473285612Sdelphij snprintf( sDeviceName, sizeof(sDeviceName), DEVICE, unit ) ; 474106163Sroberto 475285612Sdelphij snprintf( sLog, sizeof(sLog), "mode=%d dev=%s", peer->ttl, sDeviceName ) ; 476285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ; 477106163Sroberto 478106163Sroberto /* 479132451Sroberto * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf 480106163Sroberto */ 481132451Sroberto switch ( peer->ttl ) { 482106163Sroberto case 0 : 483106163Sroberto case 1 : 484285612Sdelphij rc = jjy_start_tristate_jjy01 ( unit, peer, up ) ; 485106163Sroberto break ; 486106163Sroberto case 2 : 487285612Sdelphij rc = jjy_start_cdex_jst2000 ( unit, peer, up ) ; 488106163Sroberto break ; 489182007Sroberto case 3 : 490285612Sdelphij rc = jjy_start_echokeisokuki_lt2000 ( unit, peer, up ) ; 491182007Sroberto break ; 492285612Sdelphij case 4 : 493285612Sdelphij rc = jjy_start_citizentic_jjy200 ( unit, peer, up ) ; 494285612Sdelphij break ; 495285612Sdelphij case 5 : 496285612Sdelphij rc = jjy_start_tristate_gpsclock01 ( unit, peer, up ) ; 497285612Sdelphij break ; 498285612Sdelphij case 6 : 499285612Sdelphij rc = jjy_start_seiko_tsys_tdc_300 ( unit, peer, up ) ; 500285612Sdelphij break ; 501285612Sdelphij case 100 : 502285612Sdelphij rc = jjy_start_telephone ( unit, peer, up ) ; 503285612Sdelphij break ; 504106163Sroberto default : 505285612Sdelphij if ( 101 <= peer->ttl && peer->ttl <= 180 ) { 506285612Sdelphij rc = jjy_start_telephone ( unit, peer, up ) ; 507285612Sdelphij } else { 508285612Sdelphij msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode", 509285612Sdelphij ntoa(&peer->srcadr), peer->ttl ) ; 510285612Sdelphij free ( (void*) up ) ; 511285612Sdelphij return RC_START_ERROR ; 512285612Sdelphij } 513285612Sdelphij } 514285612Sdelphij 515285612Sdelphij if ( rc != 0 ) { 516285612Sdelphij msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Initialize error", 517285612Sdelphij ntoa(&peer->srcadr), peer->ttl ) ; 518106163Sroberto free ( (void*) up ) ; 519106163Sroberto return RC_START_ERROR ; 520106163Sroberto } 521106163Sroberto 522285612Sdelphij /* Open the device */ 523285612Sdelphij fd = refclock_open ( sDeviceName, up->linespeed, up->linediscipline ) ; 524285612Sdelphij if ( fd <= 0 ) { 525285612Sdelphij free ( (void*) up ) ; 526285612Sdelphij return RC_START_ERROR ; 527285612Sdelphij } 528285612Sdelphij 529285612Sdelphij /* 530285612Sdelphij * Initialize variables 531285612Sdelphij */ 532106163Sroberto pp = peer->procptr ; 533285612Sdelphij 534285612Sdelphij pp->clockdesc = DESCRIPTION ; 535285612Sdelphij pp->unitptr = up ; 536106163Sroberto pp->io.clock_recv = jjy_receive ; 537285612Sdelphij pp->io.srcclock = peer ; 538285612Sdelphij pp->io.datalen = 0 ; 539285612Sdelphij pp->io.fd = fd ; 540106163Sroberto if ( ! io_addclock(&pp->io) ) { 541106163Sroberto close ( fd ) ; 542285612Sdelphij pp->io.fd = -1 ; 543285612Sdelphij free ( up ) ; 544285612Sdelphij pp->unitptr = NULL ; 545106163Sroberto return RC_START_ERROR ; 546106163Sroberto } 547285612Sdelphij memcpy( (char*)&pp->refid, REFID, strlen(REFID) ) ; 548106163Sroberto 549106163Sroberto peer->precision = PRECISION ; 550106163Sroberto 551285612Sdelphij snprintf( sLog, sizeof(sLog), "minpoll=%d maxpoll=%d", peer->minpoll, peer->maxpoll ) ; 552285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ; 553285612Sdelphij 554106163Sroberto return RC_START_SUCCESS ; 555106163Sroberto 556106163Sroberto} 557106163Sroberto 558106163Sroberto/**************************************************************************************************/ 559106163Sroberto/* jjy_shutdown - shutdown the clock */ 560106163Sroberto/**************************************************************************************************/ 561106163Srobertostatic void 562106163Srobertojjy_shutdown ( int unit, struct peer *peer ) 563106163Sroberto{ 564106163Sroberto 565285612Sdelphij struct jjyunit *up; 566106163Sroberto struct refclockproc *pp; 567106163Sroberto 568285612Sdelphij char sLog [ 60 ] ; 569285612Sdelphij 570106163Sroberto pp = peer->procptr ; 571285612Sdelphij up = pp->unitptr ; 572285612Sdelphij if ( -1 != pp->io.fd ) { 573285612Sdelphij io_closeclock ( &pp->io ) ; 574285612Sdelphij } 575285612Sdelphij if ( NULL != up ) { 576285612Sdelphij free ( up ) ; 577285612Sdelphij } 578106163Sroberto 579285612Sdelphij snprintf( sLog, sizeof(sLog), "JJY stopped. unit=%d mode=%d", unit, peer->ttl ) ; 580285612Sdelphij record_clock_stats( &peer->srcadr, sLog ) ; 581285612Sdelphij 582106163Sroberto} 583106163Sroberto 584106163Sroberto/**************************************************************************************************/ 585106163Sroberto/* jjy_receive - receive data from the serial interface */ 586106163Sroberto/**************************************************************************************************/ 587106163Srobertostatic void 588106163Srobertojjy_receive ( struct recvbuf *rbufp ) 589106163Sroberto{ 590285612Sdelphij#ifdef DEBUG 591285612Sdelphij static const char *sFunctionName = "jjy_receive" ; 592285612Sdelphij#endif 593106163Sroberto 594285612Sdelphij struct jjyunit *up ; 595106163Sroberto struct refclockproc *pp ; 596285612Sdelphij struct peer *peer; 597106163Sroberto 598106163Sroberto l_fp tRecvTimestamp; /* arrival timestamp */ 599106163Sroberto int rc ; 600285612Sdelphij char *pBuf, sLogText [ MAX_LOGTEXT ] ; 601316722Sdelphij size_t iLen, iCopyLen ; 602285612Sdelphij int i, j, iReadRawBuf, iBreakPosition ; 603106163Sroberto 604106163Sroberto /* 605106163Sroberto * Initialize pointers and read the timecode and timestamp 606106163Sroberto */ 607285612Sdelphij peer = rbufp->recv_peer ; 608106163Sroberto pp = peer->procptr ; 609285612Sdelphij up = pp->unitptr ; 610106163Sroberto 611106163Sroberto /* 612106163Sroberto * Get next input line 613106163Sroberto */ 614285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 615106163Sroberto 616285612Sdelphij pp->lencode = refclock_gtraw ( rbufp, pp->a_lastcode, BMAX-1, &tRecvTimestamp ) ; 617285612Sdelphij /* 3rd argument can be BMAX, but the coverity scan tool claim "Memory - corruptions (OVERRUN)" */ 618285612Sdelphij /* "a_lastcode" is defined as "char a_lastcode[BMAX]" in the ntp_refclock.h */ 619285612Sdelphij /* To avoid its claim, pass the value BMAX-1. */ 620285612Sdelphij 621106163Sroberto /* 622285612Sdelphij * Append received charaters to temporary buffer 623106163Sroberto */ 624285612Sdelphij for ( i = 0 ; 625285612Sdelphij i < pp->lencode && up->iRawBufLen < MAX_RAWBUF - 2 ; 626285612Sdelphij i ++ , up->iRawBufLen ++ ) { 627285612Sdelphij up->sRawBuf[up->iRawBufLen] = pp->a_lastcode[i] ; 628106163Sroberto } 629285612Sdelphij up->sRawBuf[up->iRawBufLen] = 0 ; 630285612Sdelphij 631285612Sdelphij 632285612Sdelphij } else { 633285612Sdelphij 634285612Sdelphij pp->lencode = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ; 635285612Sdelphij 636285612Sdelphij } 637285612Sdelphij#ifdef DEBUG 638285612Sdelphij printf( "\nrefclock_jjy.c : %s : Len=%d ", sFunctionName, pp->lencode ) ; 639285612Sdelphij for ( i = 0 ; i < pp->lencode ; i ++ ) { 640294569Sdelphij if ( iscntrl( (u_char)(pp->a_lastcode[i] & 0x7F) ) ) { 641285612Sdelphij printf( "<x%02X>", pp->a_lastcode[i] & 0xFF ) ; 642285612Sdelphij } else { 643285612Sdelphij printf( "%c", pp->a_lastcode[i] ) ; 644106163Sroberto } 645285612Sdelphij } 646285612Sdelphij printf( "\n" ) ; 647285612Sdelphij#endif 648285612Sdelphij 649285612Sdelphij /* 650285612Sdelphij * The reply with <CR><LF> gives a blank line 651285612Sdelphij */ 652285612Sdelphij 653285612Sdelphij if ( pp->lencode == 0 ) return ; 654285612Sdelphij 655285612Sdelphij /* 656285612Sdelphij * Receiving data is not expected 657285612Sdelphij */ 658285612Sdelphij 659285612Sdelphij if ( up->iProcessState == JJY_PROCESS_STATE_IDLE 660285612Sdelphij || up->iProcessState == JJY_PROCESS_STATE_DONE 661285612Sdelphij || up->iProcessState == JJY_PROCESS_STATE_ERROR ) { 662285612Sdelphij /* Discard received data */ 663285612Sdelphij up->iRawBufLen = 0 ; 664285612Sdelphij#ifdef DEBUG 665285612Sdelphij if ( debug ) { 666285612Sdelphij printf( "refclock_jjy.c : %s : Discard received data\n", sFunctionName ) ; 667285612Sdelphij } 668285612Sdelphij#endif 669285612Sdelphij return ; 670285612Sdelphij } 671285612Sdelphij 672285612Sdelphij /* 673285612Sdelphij * We get down to business 674285612Sdelphij */ 675285612Sdelphij 676285612Sdelphij pp->lastrec = tRecvTimestamp ; 677285612Sdelphij 678285612Sdelphij up->iLineCount ++ ; 679285612Sdelphij 680285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_RECEIVE ; 681285612Sdelphij up->bReceiveFlag = TRUE ; 682285612Sdelphij 683285612Sdelphij iReadRawBuf = 0 ; 684285612Sdelphij iBreakPosition = up->iRawBufLen - 1 ; 685285612Sdelphij for ( ; up->iProcessState == JJY_PROCESS_STATE_RECEIVE ; ) { 686285612Sdelphij 687285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 688285612Sdelphij 689285612Sdelphij if ( up->bWaitBreakString ) { 690285612Sdelphij iBreakPosition = getRawDataBreakPosition( up, iReadRawBuf ) ; 691285612Sdelphij if ( iBreakPosition == -1 ) { 692285612Sdelphij /* Break string have not come yet */ 693285612Sdelphij if ( up->iRawBufLen < MAX_RAWBUF - 2 694285612Sdelphij || iReadRawBuf > 0 ) { 695285612Sdelphij /* Temporary buffer is not full */ 696285612Sdelphij break ; 697285612Sdelphij } else { 698285612Sdelphij /* Temporary buffer is full */ 699285612Sdelphij iBreakPosition = up->iRawBufLen - 1 ; 700285612Sdelphij } 701285612Sdelphij } 702285612Sdelphij } else { 703285612Sdelphij iBreakPosition = up->iRawBufLen - 1 ; 704285612Sdelphij } 705285612Sdelphij 706285612Sdelphij /* Copy charaters from temporary buffer to process buffer */ 707285612Sdelphij up->iLineBufLen = up->iTextBufLen = 0 ; 708285612Sdelphij for ( i = iReadRawBuf ; i <= iBreakPosition ; i ++ ) { 709285612Sdelphij 710285612Sdelphij /* Copy all characters */ 711285612Sdelphij up->sLineBuf[up->iLineBufLen] = up->sRawBuf[i] ; 712285612Sdelphij up->iLineBufLen ++ ; 713285612Sdelphij 714285612Sdelphij /* Copy printable characters */ 715294569Sdelphij if ( ! iscntrl( (u_char)up->sRawBuf[i] ) ) { 716285612Sdelphij up->sTextBuf[up->iTextBufLen] = up->sRawBuf[i] ; 717285612Sdelphij up->iTextBufLen ++ ; 718285612Sdelphij } 719285612Sdelphij 720285612Sdelphij } 721285612Sdelphij up->sLineBuf[up->iLineBufLen] = 0 ; 722285612Sdelphij up->sTextBuf[up->iTextBufLen] = 0 ; 723285612Sdelphij#ifdef DEBUG 724285612Sdelphij printf( "refclock_jjy.c : %s : up->iLineBufLen=%d up->iTextBufLen=%d\n", 725285612Sdelphij sFunctionName, up->iLineBufLen, up->iTextBufLen ) ; 726285612Sdelphij#endif 727285612Sdelphij 728285612Sdelphij if ( up->bSkipCntrlCharOnly && up->iTextBufLen == 0 ) { 729285612Sdelphij#ifdef DEBUG 730285612Sdelphij printf( "refclock_jjy.c : %s : Skip cntrl char only : up->iRawBufLen=%d iReadRawBuf=%d iBreakPosition=%d\n", 731285612Sdelphij sFunctionName, up->iRawBufLen, iReadRawBuf, iBreakPosition ) ; 732285612Sdelphij#endif 733285612Sdelphij if ( iBreakPosition + 1 < up->iRawBufLen ) { 734285612Sdelphij iReadRawBuf = iBreakPosition + 1 ; 735285612Sdelphij continue ; 736285612Sdelphij } else { 737285612Sdelphij break ; 738285612Sdelphij } 739285612Sdelphij 740285612Sdelphij } 741285612Sdelphij 742285612Sdelphij } 743285612Sdelphij 744285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 745285612Sdelphij pBuf = up->sLineBuf ; 746285612Sdelphij iLen = up->iLineBufLen ; 747285612Sdelphij } else { 748285612Sdelphij pBuf = pp->a_lastcode ; 749285612Sdelphij iLen = pp->lencode ; 750285612Sdelphij } 751285612Sdelphij 752285612Sdelphij iCopyLen = ( iLen <= sizeof(sLogText)-1 ? iLen : sizeof(sLogText)-1 ) ; 753316722Sdelphij memcpy( sLogText, pBuf, iCopyLen ) ; 754316722Sdelphij sLogText[iCopyLen] = '\0' ; 755285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_RECEIVE, sLogText ) ; 756285612Sdelphij 757285612Sdelphij switch ( up->unittype ) { 758285612Sdelphij 759285612Sdelphij case UNITTYPE_TRISTATE_JJY01 : 760285612Sdelphij rc = jjy_receive_tristate_jjy01 ( rbufp ) ; 761285612Sdelphij break ; 762285612Sdelphij 763285612Sdelphij case UNITTYPE_CDEX_JST2000 : 764285612Sdelphij rc = jjy_receive_cdex_jst2000 ( rbufp ) ; 765285612Sdelphij break ; 766285612Sdelphij 767285612Sdelphij case UNITTYPE_ECHOKEISOKUKI_LT2000 : 768285612Sdelphij rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ; 769285612Sdelphij break ; 770285612Sdelphij 771285612Sdelphij case UNITTYPE_CITIZENTIC_JJY200 : 772285612Sdelphij rc = jjy_receive_citizentic_jjy200 ( rbufp ) ; 773285612Sdelphij break ; 774285612Sdelphij 775285612Sdelphij case UNITTYPE_TRISTATE_GPSCLOCK01 : 776285612Sdelphij rc = jjy_receive_tristate_gpsclock01 ( rbufp ) ; 777285612Sdelphij break ; 778285612Sdelphij 779285612Sdelphij case UNITTYPE_SEIKO_TIMESYS_TDC_300 : 780285612Sdelphij rc = jjy_receive_seiko_tsys_tdc_300 ( rbufp ) ; 781285612Sdelphij break ; 782285612Sdelphij 783285612Sdelphij case UNITTYPE_TELEPHONE : 784285612Sdelphij rc = jjy_receive_telephone ( rbufp ) ; 785285612Sdelphij break ; 786285612Sdelphij 787285612Sdelphij default : 788285612Sdelphij rc = JJY_RECEIVE_ERROR ; 789285612Sdelphij break ; 790285612Sdelphij 791285612Sdelphij } 792285612Sdelphij 793285612Sdelphij switch ( rc ) { 794285612Sdelphij case JJY_RECEIVE_DONE : 795285612Sdelphij case JJY_RECEIVE_SKIP : 796285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_DONE ; 797285612Sdelphij break ; 798285612Sdelphij case JJY_RECEIVE_ERROR : 799285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_ERROR ; 800285612Sdelphij break ; 801285612Sdelphij default : 802285612Sdelphij break ; 803285612Sdelphij } 804285612Sdelphij 805285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 806285612Sdelphij if ( rc == JJY_RECEIVE_UNPROCESS ) { 807106163Sroberto break ; 808106163Sroberto } 809285612Sdelphij iReadRawBuf = iBreakPosition + 1 ; 810285612Sdelphij if ( iReadRawBuf >= up->iRawBufLen ) { 811285612Sdelphij /* Processed all received data */ 812285612Sdelphij break ; 813285612Sdelphij } 814106163Sroberto } 815285612Sdelphij 816285612Sdelphij if ( up->linediscipline == LDISC_CLK ) { 817285612Sdelphij break ; 818106163Sroberto } 819285612Sdelphij 820285612Sdelphij } 821285612Sdelphij 822285612Sdelphij if ( up->linediscipline == LDISC_RAW && iReadRawBuf > 0 ) { 823285612Sdelphij for ( i = 0, j = iReadRawBuf ; j < up->iRawBufLen ; i ++, j++ ) { 824285612Sdelphij up->sRawBuf[i] = up->sRawBuf[j] ; 825285612Sdelphij } 826285612Sdelphij up->iRawBufLen -= iReadRawBuf ; 827285612Sdelphij if ( up->iRawBufLen < 0 ) { 828285612Sdelphij up->iRawBufLen = 0 ; 829285612Sdelphij } 830285612Sdelphij } 831285612Sdelphij 832285612Sdelphij up->bReceiveFlag = FALSE ; 833285612Sdelphij 834285612Sdelphij} 835285612Sdelphij 836285612Sdelphij/**************************************************************************************************/ 837285612Sdelphij 838285612Sdelphijstatic int 839285612SdelphijgetRawDataBreakPosition ( struct jjyunit *up, int iStart ) 840285612Sdelphij{ 841285612Sdelphij 842285612Sdelphij int i, j ; 843285612Sdelphij 844285612Sdelphij if ( iStart >= up->iRawBufLen ) { 845285612Sdelphij#ifdef DEBUG 846285612Sdelphij printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=-1\n", iStart ) ; 847285612Sdelphij#endif 848285612Sdelphij return -1 ; 849285612Sdelphij } 850285612Sdelphij 851285612Sdelphij for ( i = iStart ; i < up->iRawBufLen ; i ++ ) { 852285612Sdelphij 853285612Sdelphij for ( j = 0 ; up->pRawBreak[j].pString != NULL ; j ++ ) { 854285612Sdelphij 855285612Sdelphij if ( i + up->pRawBreak[j].iLength <= up->iRawBufLen ) { 856285612Sdelphij 857285612Sdelphij if ( strncmp( up->sRawBuf + i, 858285612Sdelphij up->pRawBreak[j].pString, 859285612Sdelphij up->pRawBreak[j].iLength ) == 0 ) { 860285612Sdelphij 861285612Sdelphij#ifdef DEBUG 862285612Sdelphij printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=%d\n", 863285612Sdelphij iStart, i + up->pRawBreak[j].iLength - 1 ) ; 864285612Sdelphij#endif 865285612Sdelphij return i + up->pRawBreak[j].iLength - 1 ; 866285612Sdelphij 867285612Sdelphij } 868285612Sdelphij } 869285612Sdelphij } 870285612Sdelphij } 871285612Sdelphij 872285612Sdelphij#ifdef DEBUG 873285612Sdelphij printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=-1\n", iStart ) ; 874285612Sdelphij#endif 875285612Sdelphij return -1 ; 876285612Sdelphij 877285612Sdelphij} 878285612Sdelphij 879285612Sdelphij/**************************************************************************************************/ 880285612Sdelphij/* jjy_poll - called by the transmit procedure */ 881285612Sdelphij/**************************************************************************************************/ 882285612Sdelphijstatic void 883285612Sdelphijjjy_poll ( int unit, struct peer *peer ) 884285612Sdelphij{ 885285612Sdelphij 886285612Sdelphij char sLog [ 40 ], sReach [ 9 ] ; 887285612Sdelphij 888285612Sdelphij struct jjyunit *up; 889285612Sdelphij struct refclockproc *pp; 890285612Sdelphij 891285612Sdelphij pp = peer->procptr; 892285612Sdelphij up = pp->unitptr ; 893285612Sdelphij 894285612Sdelphij if ( up->bInitError ) { 895285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, "Ignore polling because of error during initializing" ) ; 896285612Sdelphij return ; 897285612Sdelphij } 898285612Sdelphij 899285612Sdelphij if ( pp->polls > 0 && up->iLineCount == 0 ) { 900106163Sroberto /* 901285612Sdelphij * No reply for last command 902106163Sroberto */ 903285612Sdelphij refclock_report ( peer, CEVNT_TIMEOUT ) ; 904106163Sroberto } 905106163Sroberto 906285612Sdelphij pp->polls ++ ; 907106163Sroberto 908285612Sdelphij sReach[0] = peer->reach & 0x80 ? '1' : '0' ; 909285612Sdelphij sReach[1] = peer->reach & 0x40 ? '1' : '0' ; 910285612Sdelphij sReach[2] = peer->reach & 0x20 ? '1' : '0' ; 911285612Sdelphij sReach[3] = peer->reach & 0x10 ? '1' : '0' ; 912285612Sdelphij sReach[4] = peer->reach & 0x08 ? '1' : '0' ; 913285612Sdelphij sReach[5] = peer->reach & 0x04 ? '1' : '0' ; 914285612Sdelphij sReach[6] = peer->reach & 0x02 ? '1' : '0' ; 915285612Sdelphij sReach[7] = 0 ; /* This poll */ 916285612Sdelphij sReach[8] = 0 ; 917106163Sroberto 918285612Sdelphij snprintf( sLog, sizeof(sLog), "polls=%ld reach=%s", pp->polls, sReach ) ; 919285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ATTENTION, sLog ) ; 920106163Sroberto 921285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_POLL ; 922285612Sdelphij up->iCommandSeq = 0 ; 923285612Sdelphij up->iReceiveSeq = 0 ; 924285612Sdelphij up->iLineCount = 0 ; 925285612Sdelphij up->bLineError = FALSE ; 926285612Sdelphij up->iRawBufLen = 0 ; 927285612Sdelphij 928106163Sroberto switch ( up->unittype ) { 929106163Sroberto 930106163Sroberto case UNITTYPE_TRISTATE_JJY01 : 931285612Sdelphij jjy_poll_tristate_jjy01 ( unit, peer ) ; 932106163Sroberto break ; 933106163Sroberto 934106163Sroberto case UNITTYPE_CDEX_JST2000 : 935285612Sdelphij jjy_poll_cdex_jst2000 ( unit, peer ) ; 936106163Sroberto break ; 937106163Sroberto 938182007Sroberto case UNITTYPE_ECHOKEISOKUKI_LT2000 : 939285612Sdelphij jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ; 940182007Sroberto break ; 941182007Sroberto 942285612Sdelphij case UNITTYPE_CITIZENTIC_JJY200 : 943285612Sdelphij jjy_poll_citizentic_jjy200 ( unit, peer ) ; 944285612Sdelphij break ; 945200576Sroberto 946285612Sdelphij case UNITTYPE_TRISTATE_GPSCLOCK01 : 947285612Sdelphij jjy_poll_tristate_gpsclock01 ( unit, peer ) ; 948285612Sdelphij break ; 949285612Sdelphij 950285612Sdelphij case UNITTYPE_SEIKO_TIMESYS_TDC_300 : 951285612Sdelphij jjy_poll_seiko_tsys_tdc_300 ( unit, peer ) ; 952285612Sdelphij break ; 953285612Sdelphij 954285612Sdelphij case UNITTYPE_TELEPHONE : 955285612Sdelphij jjy_poll_telephone ( unit, peer ) ; 956285612Sdelphij break ; 957285612Sdelphij 958106163Sroberto default : 959106163Sroberto break ; 960106163Sroberto 961106163Sroberto } 962106163Sroberto 963285612Sdelphij} 964285612Sdelphij 965285612Sdelphij/**************************************************************************************************/ 966285612Sdelphij/* jjy_timer - called at one-second intervals */ 967285612Sdelphij/**************************************************************************************************/ 968285612Sdelphijstatic void 969285612Sdelphijjjy_timer ( int unit, struct peer *peer ) 970285612Sdelphij{ 971285612Sdelphij 972285612Sdelphij struct refclockproc *pp ; 973285612Sdelphij struct jjyunit *up ; 974285612Sdelphij 975285612Sdelphij#ifdef DEBUG 976285612Sdelphij if ( debug ) { 977285612Sdelphij printf ( "refclock_jjy.c : jjy_timer\n" ) ; 978106163Sroberto } 979285612Sdelphij#endif 980106163Sroberto 981285612Sdelphij pp = peer->procptr ; 982285612Sdelphij up = pp->unitptr ; 983106163Sroberto 984285612Sdelphij if ( up->bReceiveFlag ) { 985285612Sdelphij#ifdef DEBUG 986285612Sdelphij if ( debug ) { 987285612Sdelphij printf ( "refclock_jjy.c : jjy_timer : up->bReceiveFlag= TRUE : Timer skipped.\n" ) ; 988106163Sroberto } 989285612Sdelphij#endif 990106163Sroberto return ; 991106163Sroberto } 992106163Sroberto 993285612Sdelphij switch ( up->unittype ) { 994285612Sdelphij 995285612Sdelphij case UNITTYPE_TELEPHONE : 996285612Sdelphij jjy_timer_telephone ( unit, peer ) ; 997285612Sdelphij break ; 998285612Sdelphij 999285612Sdelphij default : 1000285612Sdelphij break ; 1001285612Sdelphij 1002285612Sdelphij } 1003285612Sdelphij 1004285612Sdelphij} 1005285612Sdelphij 1006285612Sdelphij/**************************************************************************************************/ 1007285612Sdelphij/* jjy_synctime */ 1008285612Sdelphij/**************************************************************************************************/ 1009285612Sdelphijstatic void 1010285612Sdelphijjjy_synctime ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 1011285612Sdelphij{ 1012285612Sdelphij 1013285612Sdelphij char sLog [ 80 ], cStatus ; 1014285612Sdelphij const char *pStatus ; 1015285612Sdelphij 1016106163Sroberto pp->year = up->year ; 1017285612Sdelphij pp->day = ymd2yd( up->year, up->month, up->day ) ; 1018106163Sroberto pp->hour = up->hour ; 1019106163Sroberto pp->minute = up->minute ; 1020106163Sroberto pp->second = up->second ; 1021285612Sdelphij pp->nsec = up->msecond * 1000000 ; 1022106163Sroberto 1023106163Sroberto /* 1024106163Sroberto * JST to UTC 1025106163Sroberto */ 1026106163Sroberto pp->hour -= 9 ; 1027106163Sroberto if ( pp->hour < 0 ) { 1028106163Sroberto pp->hour += 24 ; 1029106163Sroberto pp->day -- ; 1030106163Sroberto if ( pp->day < 1 ) { 1031106163Sroberto pp->year -- ; 1032285612Sdelphij pp->day = ymd2yd( pp->year, 12, 31 ) ; 1033106163Sroberto } 1034106163Sroberto } 1035285612Sdelphij 1036285612Sdelphij /* 1037285612Sdelphij * Process the new sample in the median filter and determine the 1038285612Sdelphij * timecode timestamp. 1039285612Sdelphij */ 1040285612Sdelphij 1041285612Sdelphij if ( ! refclock_process( pp ) ) { 1042285612Sdelphij refclock_report( peer, CEVNT_BADTIME ) ; 1043285612Sdelphij return ; 1044285612Sdelphij } 1045285612Sdelphij 1046285612Sdelphij pp->lastref = pp->lastrec ; 1047285612Sdelphij 1048285612Sdelphij refclock_receive( peer ) ; 1049285612Sdelphij 1050285612Sdelphij /* 1051285612Sdelphij * Write into the clockstats file 1052285612Sdelphij */ 1053285612Sdelphij snprintf ( sLog, sizeof(sLog), 1054285612Sdelphij "%04d/%02d/%02d %02d:%02d:%02d.%03d JST ( %04d/%03d %02d:%02d:%02d.%03d UTC )", 1055285612Sdelphij up->year, up->month, up->day, 1056285612Sdelphij up->hour, up->minute, up->second, up->msecond, 1057285612Sdelphij pp->year, pp->day, pp->hour, pp->minute, pp->second, 1058285612Sdelphij (int)(pp->nsec/1000000) ) ; 1059285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ATTENTION, sLog ) ; 1060285612Sdelphij 1061285612Sdelphij cStatus = ' ' ; 1062285612Sdelphij pStatus = "" ; 1063285612Sdelphij 1064285612Sdelphij switch ( peer->status ) { 1065285612Sdelphij case 0 : cStatus = ' ' ; pStatus = "Reject" ; break ; 1066285612Sdelphij case 1 : cStatus = 'x' ; pStatus = "FalseTick" ; break ; 1067285612Sdelphij case 2 : cStatus = '.' ; pStatus = "Excess" ; break ; 1068285612Sdelphij case 3 : cStatus = '-' ; pStatus = "Outlier" ; break ; 1069285612Sdelphij case 4 : cStatus = '+' ; pStatus = "Candidate" ; break ; 1070285612Sdelphij case 5 : cStatus = '#' ; pStatus = "Selected" ; break ; 1071285612Sdelphij case 6 : cStatus = '*' ; pStatus = "Sys.Peer" ; break ; 1072285612Sdelphij case 7 : cStatus = 'o' ; pStatus = "PPS.Peer" ; break ; 1073285612Sdelphij default : break ; 1074285612Sdelphij } 1075285612Sdelphij 1076285612Sdelphij snprintf ( sLog, sizeof(sLog), 1077285612Sdelphij "status %d [%c] %s : offset %3.3f mSec. : jitter %3.3f mSec.", 1078285612Sdelphij peer->status, cStatus, pStatus, peer->offset * 1000, peer->jitter * 1000 ) ; 1079285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ; 1080285612Sdelphij 1081285612Sdelphij} 1082285612Sdelphij 1083285612Sdelphij/*################################################################################################*/ 1084285612Sdelphij/*################################################################################################*/ 1085285612Sdelphij/*## ##*/ 1086285612Sdelphij/*## The Tristate Ltd. JJY receiver TS-JJY01, TS-JJY02 ##*/ 1087285612Sdelphij/*## ##*/ 1088285612Sdelphij/*## server 127.127.40.X mode 1 ##*/ 1089285612Sdelphij/*## ##*/ 1090285612Sdelphij/*################################################################################################*/ 1091285612Sdelphij/*################################################################################################*/ 1092285612Sdelphij/* */ 1093285612Sdelphij/* Command Response Remarks */ 1094285612Sdelphij/* -------------------- ---------------------------------------- ---------------------------- */ 1095285612Sdelphij/* dcst<CR><LF> VALID<CR><LF> or INVALID<CR><LF> */ 1096285612Sdelphij/* stus<CR><LF> ADJUSTED<CR><LF> or UNADJUSTED<CR><LF> */ 1097285612Sdelphij/* date<CR><LF> YYYY/MM/DD XXX<CR><LF> XXX is the day of the week */ 1098285612Sdelphij/* time<CR><LF> HH:MM:SS<CR><LF> Not used by this driver */ 1099285612Sdelphij/* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */ 1100285612Sdelphij/* */ 1101285612Sdelphij/*################################################################################################*/ 1102285612Sdelphij 1103285612Sdelphij#define TS_JJY01_COMMAND_NUMBER_DATE 1 1104285612Sdelphij#define TS_JJY01_COMMAND_NUMBER_TIME 2 1105285612Sdelphij#define TS_JJY01_COMMAND_NUMBER_STIM 3 1106285612Sdelphij#define TS_JJY01_COMMAND_NUMBER_STUS 4 1107285612Sdelphij#define TS_JJY01_COMMAND_NUMBER_DCST 5 1108285612Sdelphij 1109285612Sdelphij#define TS_JJY01_REPLY_DATE "yyyy/mm/dd www" 1110285612Sdelphij#define TS_JJY01_REPLY_STIM "hh:mm:ss" 1111285612Sdelphij#define TS_JJY01_REPLY_STUS_ADJUSTED "adjusted" 1112285612Sdelphij#define TS_JJY01_REPLY_STUS_UNADJUSTED "unadjusted" 1113285612Sdelphij#define TS_JJY01_REPLY_DCST_VALID "valid" 1114285612Sdelphij#define TS_JJY01_REPLY_DCST_INVALID "invalid" 1115285612Sdelphij 1116285612Sdelphij#define TS_JJY01_REPLY_LENGTH_DATE 14 /* Length without <CR><LF> */ 1117285612Sdelphij#define TS_JJY01_REPLY_LENGTH_TIME 8 /* Length without <CR><LF> */ 1118285612Sdelphij#define TS_JJY01_REPLY_LENGTH_STIM 8 /* Length without <CR><LF> */ 1119285612Sdelphij#define TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED 8 /* Length without <CR><LF> */ 1120285612Sdelphij#define TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED 10 /* Length without <CR><LF> */ 1121285612Sdelphij#define TS_JJY01_REPLY_LENGTH_DCST_VALID 5 /* Length without <CR><LF> */ 1122285612Sdelphij#define TS_JJY01_REPLY_LENGTH_DCST_INVALID 7 /* Length without <CR><LF> */ 1123285612Sdelphij 1124285612Sdelphijstatic struct 1125285612Sdelphij{ 1126285612Sdelphij const char commandNumber ; 1127285612Sdelphij const char *command ; 1128285612Sdelphij int commandLength ; 1129285612Sdelphij int iExpectedReplyLength [ 2 ] ; 1130285612Sdelphij} tristate_jjy01_command_sequence[] = 1131285612Sdelphij{ 1132285612Sdelphij { 0, NULL, 0, { 0, 0 } }, /* Idle */ 1133285612Sdelphij { TS_JJY01_COMMAND_NUMBER_DCST, "dcst\r\n", 6, { TS_JJY01_REPLY_LENGTH_DCST_VALID , TS_JJY01_REPLY_LENGTH_DCST_INVALID } }, 1134285612Sdelphij { TS_JJY01_COMMAND_NUMBER_STUS, "stus\r\n", 6, { TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED, TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED } }, 1135285612Sdelphij { TS_JJY01_COMMAND_NUMBER_TIME, "time\r\n", 6, { TS_JJY01_REPLY_LENGTH_TIME , TS_JJY01_REPLY_LENGTH_TIME } }, 1136285612Sdelphij { TS_JJY01_COMMAND_NUMBER_DATE, "date\r\n", 6, { TS_JJY01_REPLY_LENGTH_DATE , TS_JJY01_REPLY_LENGTH_DATE } }, 1137285612Sdelphij { TS_JJY01_COMMAND_NUMBER_STIM, "stim\r\n", 6, { TS_JJY01_REPLY_LENGTH_STIM , TS_JJY01_REPLY_LENGTH_STIM } }, 1138285612Sdelphij /* End of command */ 1139285612Sdelphij { 0, NULL, 0, { 0, 0 } } 1140285612Sdelphij} ; 1141285612Sdelphij 1142285612Sdelphij/**************************************************************************************************/ 1143285612Sdelphij 1144285612Sdelphijstatic int 1145285612Sdelphijjjy_start_tristate_jjy01 ( int unit, struct peer *peer, struct jjyunit *up ) 1146285612Sdelphij{ 1147285612Sdelphij 1148285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Tristate Ltd. TS-JJY01, TS-JJY02" ) ; 1149285612Sdelphij 1150285612Sdelphij up->unittype = UNITTYPE_TRISTATE_JJY01 ; 1151285612Sdelphij up->linespeed = SPEED232_TRISTATE_JJY01 ; 1152285612Sdelphij up->linediscipline = LDISC_CLK ; 1153285612Sdelphij 1154285612Sdelphij return 0 ; 1155285612Sdelphij 1156285612Sdelphij} 1157285612Sdelphij 1158285612Sdelphij/**************************************************************************************************/ 1159285612Sdelphij 1160285612Sdelphijstatic int 1161285612Sdelphijjjy_receive_tristate_jjy01 ( struct recvbuf *rbufp ) 1162285612Sdelphij{ 1163285612Sdelphij struct jjyunit *up ; 1164285612Sdelphij struct refclockproc *pp ; 1165285612Sdelphij struct peer *peer; 1166285612Sdelphij 1167294569Sdelphij char * pBuf ; 1168294569Sdelphij char sLog [ 100 ] ; 1169294569Sdelphij int iLen ; 1170294569Sdelphij int rc ; 1171285612Sdelphij 1172294569Sdelphij const char * pCmd ; 1173294569Sdelphij int iCmdLen ; 1174285612Sdelphij 1175285612Sdelphij /* Initialize pointers */ 1176285612Sdelphij 1177285612Sdelphij peer = rbufp->recv_peer ; 1178285612Sdelphij pp = peer->procptr ; 1179285612Sdelphij up = pp->unitptr ; 1180285612Sdelphij 1181285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 1182285612Sdelphij pBuf = up->sTextBuf ; 1183285612Sdelphij iLen = up->iTextBufLen ; 1184285612Sdelphij } else { 1185285612Sdelphij pBuf = pp->a_lastcode ; 1186285612Sdelphij iLen = pp->lencode ; 1187285612Sdelphij } 1188285612Sdelphij 1189285612Sdelphij DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_tristate_jjy01", iLen ) ; 1190285612Sdelphij 1191285612Sdelphij /* Check expected reply */ 1192285612Sdelphij 1193285612Sdelphij if ( tristate_jjy01_command_sequence[up->iCommandSeq].command == NULL ) { 1194285612Sdelphij /* Command sequence has not been started, or has been completed */ 1195285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY, 1196285612Sdelphij pBuf ) ; 1197285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1198285612Sdelphij up->bLineError = TRUE ; 1199285612Sdelphij return JJY_RECEIVE_ERROR ; 1200285612Sdelphij } 1201285612Sdelphij 1202285612Sdelphij /* Check reply length */ 1203285612Sdelphij 1204285612Sdelphij if ( iLen != tristate_jjy01_command_sequence[up->iCommandSeq].iExpectedReplyLength[0] 1205285612Sdelphij && iLen != tristate_jjy01_command_sequence[up->iCommandSeq].iExpectedReplyLength[1] ) { 1206285612Sdelphij /* Unexpected reply length */ 1207285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH, 1208285612Sdelphij iLen ) ; 1209285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1210285612Sdelphij up->bLineError = TRUE ; 1211285612Sdelphij return JJY_RECEIVE_ERROR ; 1212285612Sdelphij } 1213285612Sdelphij 1214285612Sdelphij /* Parse reply */ 1215285612Sdelphij 1216285612Sdelphij switch ( tristate_jjy01_command_sequence[up->iCommandSeq].commandNumber ) { 1217285612Sdelphij 1218285612Sdelphij case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */ 1219285612Sdelphij 1220285612Sdelphij rc = sscanf ( pBuf, "%4d/%2d/%2d", 1221285612Sdelphij &up->year, &up->month, &up->day ) ; 1222285612Sdelphij 1223285612Sdelphij if ( rc != 3 || up->year < 2000 || 2099 <= up->year 1224285612Sdelphij || up->month < 1 || 12 < up->month 1225285612Sdelphij || up->day < 1 || 31 < up->day ) { 1226285612Sdelphij /* Invalid date */ 1227285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE, 1228285612Sdelphij rc, up->year, up->month, up->day ) ; 1229285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1230285612Sdelphij up->bLineError = TRUE ; 1231285612Sdelphij return JJY_RECEIVE_ERROR ; 1232285612Sdelphij } 1233285612Sdelphij 1234285612Sdelphij break ; 1235285612Sdelphij 1236285612Sdelphij case TS_JJY01_COMMAND_NUMBER_TIME : /* HH:MM:SS */ 1237285612Sdelphij case TS_JJY01_COMMAND_NUMBER_STIM : /* HH:MM:SS */ 1238285612Sdelphij 1239285612Sdelphij if ( up->iTimestampCount >= 2 ) { 1240285612Sdelphij /* Too many time reply */ 1241285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY, 1242285612Sdelphij up->iTimestampCount ) ; 1243285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1244285612Sdelphij up->bLineError = TRUE ; 1245285612Sdelphij return JJY_RECEIVE_ERROR ; 1246285612Sdelphij } 1247285612Sdelphij 1248285612Sdelphij rc = sscanf ( pBuf, "%2d:%2d:%2d", 1249285612Sdelphij &up->hour, &up->minute, &up->second ) ; 1250285612Sdelphij 1251285612Sdelphij if ( rc != 3 || up->hour > 23 || up->minute > 59 || 1252285612Sdelphij up->second > 60 ) { 1253285612Sdelphij /* Invalid time */ 1254285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME, 1255285612Sdelphij rc, up->hour, up->minute, up->second ) ; 1256285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1257285612Sdelphij up->bLineError = TRUE ; 1258285612Sdelphij return JJY_RECEIVE_ERROR ; 1259285612Sdelphij } 1260285612Sdelphij 1261285612Sdelphij up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ; 1262285612Sdelphij 1263285612Sdelphij up->iTimestampCount++ ; 1264285612Sdelphij 1265285612Sdelphij up->msecond = 0 ; 1266285612Sdelphij 1267285612Sdelphij break ; 1268285612Sdelphij 1269285612Sdelphij case TS_JJY01_COMMAND_NUMBER_STUS : 1270285612Sdelphij 1271285612Sdelphij if ( strncmp( pBuf, TS_JJY01_REPLY_STUS_ADJUSTED, 1272285612Sdelphij TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED ) == 0 1273285612Sdelphij || strncmp( pBuf, TS_JJY01_REPLY_STUS_UNADJUSTED, 1274285612Sdelphij TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED ) == 0 ) { 1275285612Sdelphij /* Good */ 1276285612Sdelphij } else { 1277285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 1278285612Sdelphij pBuf ) ; 1279285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1280285612Sdelphij up->bLineError = TRUE ; 1281285612Sdelphij return JJY_RECEIVE_ERROR ; 1282285612Sdelphij } 1283285612Sdelphij 1284285612Sdelphij break ; 1285285612Sdelphij 1286285612Sdelphij case TS_JJY01_COMMAND_NUMBER_DCST : 1287285612Sdelphij 1288285612Sdelphij if ( strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID, 1289285612Sdelphij TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0 1290285612Sdelphij || strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID, 1291285612Sdelphij TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) { 1292285612Sdelphij /* Good */ 1293285612Sdelphij } else { 1294285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 1295285612Sdelphij pBuf ) ; 1296285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1297285612Sdelphij up->bLineError = TRUE ; 1298285612Sdelphij return JJY_RECEIVE_ERROR ; 1299285612Sdelphij } 1300285612Sdelphij 1301285612Sdelphij break ; 1302285612Sdelphij 1303285612Sdelphij default : /* Unexpected reply */ 1304285612Sdelphij 1305285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 1306285612Sdelphij pBuf ) ; 1307285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1308285612Sdelphij up->bLineError = TRUE ; 1309285612Sdelphij return JJY_RECEIVE_ERROR ; 1310285612Sdelphij 1311285612Sdelphij } 1312285612Sdelphij 1313285612Sdelphij if ( up->iTimestampCount == 2 ) { 1314285612Sdelphij /* Process date and time */ 1315285612Sdelphij 1316285612Sdelphij if ( up->iTimestamp[1] - 2 <= up->iTimestamp[0] 1317285612Sdelphij && up->iTimestamp[0] <= up->iTimestamp[1] ) { 1318285612Sdelphij /* 3 commands (time,date,stim) was excuted in two seconds */ 1319285612Sdelphij jjy_synctime( peer, pp, up ) ; 1320285612Sdelphij return JJY_RECEIVE_DONE ; 1321285612Sdelphij } else if ( up->iTimestamp[0] > up->iTimestamp[1] ) { 1322285612Sdelphij /* Over midnight, and date is unsure */ 1323285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2, 1324285612Sdelphij up->iTimestamp[0], up->iTimestamp[1] ) ; 1325285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ; 1326285612Sdelphij return JJY_RECEIVE_SKIP ; 1327285612Sdelphij } else { 1328285612Sdelphij /* Slow reply */ 1329285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2, 1330285612Sdelphij up->iTimestamp[0], up->iTimestamp[1] ) ; 1331285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1332285612Sdelphij up->bLineError = TRUE ; 1333285612Sdelphij return JJY_RECEIVE_ERROR ; 1334285612Sdelphij } 1335285612Sdelphij 1336285612Sdelphij } 1337285612Sdelphij 1338285612Sdelphij /* Issue next command */ 1339285612Sdelphij 1340285612Sdelphij if ( tristate_jjy01_command_sequence[up->iCommandSeq].command != NULL ) { 1341285612Sdelphij up->iCommandSeq ++ ; 1342285612Sdelphij } 1343285612Sdelphij 1344285612Sdelphij if ( tristate_jjy01_command_sequence[up->iCommandSeq].command == NULL ) { 1345285612Sdelphij /* Command sequence completed */ 1346285612Sdelphij return JJY_RECEIVE_DONE ; 1347285612Sdelphij } 1348285612Sdelphij 1349285612Sdelphij pCmd = tristate_jjy01_command_sequence[up->iCommandSeq].command ; 1350285612Sdelphij iCmdLen = tristate_jjy01_command_sequence[up->iCommandSeq].commandLength ; 1351285612Sdelphij if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 1352285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 1353285612Sdelphij } 1354285612Sdelphij 1355285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 1356285612Sdelphij 1357285612Sdelphij return JJY_RECEIVE_WAIT ; 1358285612Sdelphij 1359285612Sdelphij} 1360285612Sdelphij 1361285612Sdelphij/**************************************************************************************************/ 1362285612Sdelphij 1363285612Sdelphijstatic void 1364285612Sdelphijjjy_poll_tristate_jjy01 ( int unit, struct peer *peer ) 1365285612Sdelphij{ 1366106163Sroberto#ifdef DEBUG 1367285612Sdelphij static const char *sFunctionName = "jjy_poll_tristate_jjy01" ; 1368285612Sdelphij#endif 1369285612Sdelphij 1370285612Sdelphij struct refclockproc *pp ; 1371285612Sdelphij struct jjyunit *up ; 1372285612Sdelphij 1373294569Sdelphij const char * pCmd ; 1374294569Sdelphij int iCmdLen ; 1375285612Sdelphij 1376285612Sdelphij pp = peer->procptr; 1377285612Sdelphij up = pp->unitptr ; 1378285612Sdelphij 1379285612Sdelphij up->bLineError = FALSE ; 1380285612Sdelphij up->iTimestampCount = 0 ; 1381285612Sdelphij 1382285612Sdelphij if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) { 1383285612Sdelphij /* Skip "dcst" and "stus" commands */ 1384285612Sdelphij up->iCommandSeq = 2 ; 1385285612Sdelphij up->iLineCount = 2 ; 1386285612Sdelphij } 1387285612Sdelphij 1388285612Sdelphij#ifdef DEBUG 1389106163Sroberto if ( debug ) { 1390285612Sdelphij printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->iLineCount=%d\n", 1391285612Sdelphij sFunctionName, pp->sloppyclockflag, CLK_FLAG1, 1392285612Sdelphij up->iLineCount ) ; 1393106163Sroberto } 1394106163Sroberto#endif 1395106163Sroberto 1396106163Sroberto /* 1397285612Sdelphij * Send a first command 1398106163Sroberto */ 1399182007Sroberto 1400285612Sdelphij up->iCommandSeq ++ ; 1401182007Sroberto 1402285612Sdelphij pCmd = tristate_jjy01_command_sequence[up->iCommandSeq].command ; 1403285612Sdelphij iCmdLen = tristate_jjy01_command_sequence[up->iCommandSeq].commandLength ; 1404285612Sdelphij if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 1405285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 1406106163Sroberto } 1407106163Sroberto 1408285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 1409182007Sroberto 1410106163Sroberto} 1411106163Sroberto 1412285612Sdelphij/*################################################################################################*/ 1413285612Sdelphij/*################################################################################################*/ 1414285612Sdelphij/*## ##*/ 1415285612Sdelphij/*## The C-DEX Co. Ltd. JJY receiver JST2000 ##*/ 1416285612Sdelphij/*## ##*/ 1417285612Sdelphij/*## server 127.127.40.X mode 2 ##*/ 1418285612Sdelphij/*## ##*/ 1419285612Sdelphij/*################################################################################################*/ 1420285612Sdelphij/*################################################################################################*/ 1421285612Sdelphij/* */ 1422285612Sdelphij/* Command Response Remarks */ 1423285612Sdelphij/* -------------------- ---------------------------------------- ---------------------------- */ 1424285612Sdelphij/* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> J is a fixed character */ 1425285612Sdelphij/* */ 1426285612Sdelphij/*################################################################################################*/ 1427285612Sdelphij 1428285612Sdelphijstatic struct jjyRawDataBreak cdex_jst2000_raw_break [ ] = 1429285612Sdelphij{ 1430285612Sdelphij { "\x03", 1 }, { NULL, 0 } 1431285612Sdelphij} ; 1432285612Sdelphij 1433106163Sroberto/**************************************************************************************************/ 1434106163Sroberto 1435106163Srobertostatic int 1436285612Sdelphijjjy_start_cdex_jst2000 ( int unit, struct peer *peer, struct jjyunit *up ) 1437106163Sroberto{ 1438106163Sroberto 1439285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: C-DEX Co. Ltd. JST2000" ) ; 1440182007Sroberto 1441285612Sdelphij up->unittype = UNITTYPE_CDEX_JST2000 ; 1442285612Sdelphij up->linespeed = SPEED232_CDEX_JST2000 ; 1443285612Sdelphij up->linediscipline = LDISC_RAW ; 1444285612Sdelphij 1445285612Sdelphij up->pRawBreak = cdex_jst2000_raw_break ; 1446285612Sdelphij up->bWaitBreakString = TRUE ; 1447285612Sdelphij 1448285612Sdelphij up->bSkipCntrlCharOnly = FALSE ; 1449285612Sdelphij 1450285612Sdelphij return 0 ; 1451285612Sdelphij 1452285612Sdelphij} 1453285612Sdelphij 1454285612Sdelphij/**************************************************************************************************/ 1455285612Sdelphij 1456285612Sdelphijstatic int 1457285612Sdelphijjjy_receive_cdex_jst2000 ( struct recvbuf *rbufp ) 1458285612Sdelphij{ 1459285612Sdelphij 1460106163Sroberto struct jjyunit *up ; 1461106163Sroberto struct refclockproc *pp ; 1462285612Sdelphij struct peer *peer ; 1463106163Sroberto 1464285612Sdelphij char *pBuf, sLog [ 100 ] ; 1465106163Sroberto int iLen ; 1466106163Sroberto int rc ; 1467106163Sroberto 1468285612Sdelphij /* Initialize pointers */ 1469285612Sdelphij 1470285612Sdelphij peer = rbufp->recv_peer ; 1471285612Sdelphij pp = peer->procptr ; 1472285612Sdelphij up = pp->unitptr ; 1473285612Sdelphij 1474285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 1475285612Sdelphij pBuf = up->sTextBuf ; 1476285612Sdelphij iLen = up->iTextBufLen ; 1477285612Sdelphij } else { 1478285612Sdelphij pBuf = pp->a_lastcode ; 1479285612Sdelphij iLen = pp->lencode ; 1480285612Sdelphij } 1481285612Sdelphij 1482285612Sdelphij DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_cdex_jst2000", iLen ) ; 1483285612Sdelphij 1484285612Sdelphij /* Check expected reply */ 1485285612Sdelphij 1486285612Sdelphij if ( up->iCommandSeq != 1 ) { 1487285612Sdelphij /* Command sequence has not been started, or has been completed */ 1488285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY, 1489285612Sdelphij pBuf ) ; 1490285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1491285612Sdelphij up->bLineError = TRUE ; 1492285612Sdelphij return JJY_RECEIVE_ERROR ; 1493285612Sdelphij } 1494285612Sdelphij 1495285612Sdelphij /* Wait until ETX comes */ 1496285612Sdelphij 1497285612Sdelphij if ( up->iLineBufLen < 17 || up->sLineBuf[up->iLineBufLen-1] != 0x03 ) { 1498285612Sdelphij return JJY_RECEIVE_UNPROCESS ; 1499285612Sdelphij } 1500285612Sdelphij 1501285612Sdelphij /* Check reply length */ 1502285612Sdelphij 1503285612Sdelphij if ( iLen != 15 ) { 1504285612Sdelphij /* Unexpected reply length */ 1505285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH, 1506285612Sdelphij iLen ) ; 1507285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1508285612Sdelphij up->bLineError = TRUE ; 1509285612Sdelphij return JJY_RECEIVE_ERROR ; 1510285612Sdelphij } 1511285612Sdelphij 1512310419Sdelphij /* JYYMMDDWHHMMSSS */ 1513285612Sdelphij 1514310419Sdelphij rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d", 1515285612Sdelphij &up->year, &up->month, &up->day, 1516285612Sdelphij &up->hour, &up->minute, &up->second, 1517285612Sdelphij &up->msecond ) ; 1518285612Sdelphij 1519285612Sdelphij if ( rc != 7 || up->month < 1 || up->month > 12 || 1520285612Sdelphij up->day < 1 || up->day > 31 || up->hour > 23 || 1521285612Sdelphij up->minute > 59 || up->second > 60 ) { 1522285612Sdelphij /* Invalid date and time */ 1523285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME, 1524285612Sdelphij rc, up->year, up->month, up->day, 1525285612Sdelphij up->hour, up->minute, up->second ) ; 1526285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1527285612Sdelphij up->bLineError = TRUE ; 1528285612Sdelphij return JJY_RECEIVE_ERROR ; 1529285612Sdelphij } 1530285612Sdelphij 1531285612Sdelphij up->year += 2000 ; 1532285612Sdelphij up->msecond *= 100 ; 1533285612Sdelphij 1534285612Sdelphij jjy_synctime( peer, pp, up ) ; 1535285612Sdelphij 1536285612Sdelphij return JJY_RECEIVE_DONE ; 1537285612Sdelphij 1538285612Sdelphij} 1539285612Sdelphij 1540285612Sdelphij/**************************************************************************************************/ 1541285612Sdelphij 1542285612Sdelphijstatic void 1543285612Sdelphijjjy_poll_cdex_jst2000 ( int unit, struct peer *peer ) 1544285612Sdelphij{ 1545285612Sdelphij 1546285612Sdelphij struct refclockproc *pp ; 1547285612Sdelphij struct jjyunit *up ; 1548285612Sdelphij 1549285612Sdelphij pp = peer->procptr ; 1550285612Sdelphij up = pp->unitptr ; 1551285612Sdelphij 1552285612Sdelphij up->bLineError = FALSE ; 1553285612Sdelphij up->iRawBufLen = 0 ; 1554285612Sdelphij up->iLineBufLen = 0 ; 1555285612Sdelphij up->iTextBufLen = 0 ; 1556285612Sdelphij 1557106163Sroberto /* 1558285612Sdelphij * Send "<ENQ>1J<ETX>" command 1559106163Sroberto */ 1560285612Sdelphij 1561285612Sdelphij up->iCommandSeq ++ ; 1562285612Sdelphij 1563285612Sdelphij if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) { 1564285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 1565285612Sdelphij } 1566285612Sdelphij 1567285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, "\0051J\003" ) ; 1568285612Sdelphij 1569285612Sdelphij} 1570285612Sdelphij 1571285612Sdelphij/*################################################################################################*/ 1572285612Sdelphij/*################################################################################################*/ 1573285612Sdelphij/*## ##*/ 1574285612Sdelphij/*## The Echo Keisokuki Co. Ltd. JJY receiver LT2000 ##*/ 1575285612Sdelphij/*## ##*/ 1576285612Sdelphij/*## server 127.127.40.X mode 3 ##*/ 1577285612Sdelphij/*## ##*/ 1578285612Sdelphij/*################################################################################################*/ 1579285612Sdelphij/*################################################################################################*/ 1580285612Sdelphij/* */ 1581285612Sdelphij/* Command Response Remarks */ 1582285612Sdelphij/* -------------------- ---------------------------------------- ---------------------------- */ 1583285612Sdelphij/* # Mode 1 ( Request & Send ) */ 1584285612Sdelphij/* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */ 1585285612Sdelphij/* C Mode 2 ( Continuous ) */ 1586285612Sdelphij/* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> 0.5 sec before time stamp */ 1587285612Sdelphij/* <SUB> Second signal */ 1588285612Sdelphij/* */ 1589285612Sdelphij/*################################################################################################*/ 1590285612Sdelphij 1591285612Sdelphij#define ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND 1 1592285612Sdelphij#define ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS 2 1593285612Sdelphij#define ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS 3 1594285612Sdelphij 1595285612Sdelphij#define ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND "#" 1596285612Sdelphij#define ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_TIME "T" 1597285612Sdelphij#define ECHOKEISOKUKI_LT2000_COMMAND_CONTINUOUS "C" 1598285612Sdelphij 1599285612Sdelphij/**************************************************************************************************/ 1600285612Sdelphij 1601285612Sdelphijstatic int 1602285612Sdelphijjjy_start_echokeisokuki_lt2000 ( int unit, struct peer *peer, struct jjyunit *up ) 1603285612Sdelphij{ 1604285612Sdelphij 1605285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Echo Keisokuki Co. Ltd. LT2000" ) ; 1606285612Sdelphij 1607285612Sdelphij up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ; 1608285612Sdelphij up->linespeed = SPEED232_ECHOKEISOKUKI_LT2000 ; 1609285612Sdelphij up->linediscipline = LDISC_CLK ; 1610285612Sdelphij 1611285612Sdelphij up->operationmode = ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ; 1612285612Sdelphij 1613285612Sdelphij return 0 ; 1614285612Sdelphij 1615285612Sdelphij} 1616285612Sdelphij 1617285612Sdelphij/**************************************************************************************************/ 1618285612Sdelphij 1619285612Sdelphijstatic int 1620285612Sdelphijjjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp ) 1621285612Sdelphij{ 1622285612Sdelphij 1623285612Sdelphij struct jjyunit *up ; 1624285612Sdelphij struct refclockproc *pp ; 1625285612Sdelphij struct peer *peer; 1626285612Sdelphij 1627285612Sdelphij char *pBuf, sLog [ 100 ], sErr [ 60 ] ; 1628285612Sdelphij int iLen ; 1629285612Sdelphij int rc ; 1630285612Sdelphij int i, ibcc, ibcc1, ibcc2 ; 1631285612Sdelphij 1632285612Sdelphij /* Initialize pointers */ 1633285612Sdelphij 1634285612Sdelphij peer = rbufp->recv_peer ; 1635106163Sroberto pp = peer->procptr ; 1636285612Sdelphij up = pp->unitptr ; 1637106163Sroberto 1638106163Sroberto if ( up->linediscipline == LDISC_RAW ) { 1639285612Sdelphij pBuf = up->sTextBuf ; 1640285612Sdelphij iLen = up->iTextBufLen ; 1641106163Sroberto } else { 1642285612Sdelphij pBuf = pp->a_lastcode ; 1643285612Sdelphij iLen = pp->lencode ; 1644106163Sroberto } 1645106163Sroberto 1646285612Sdelphij DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_echokeisokuki_lt2000", iLen ) ; 1647106163Sroberto 1648285612Sdelphij /* Check reply length */ 1649106163Sroberto 1650285612Sdelphij if ( ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND 1651285612Sdelphij && iLen != 15 ) 1652285612Sdelphij || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS 1653285612Sdelphij && iLen != 17 ) 1654285612Sdelphij || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS 1655285612Sdelphij && iLen != 17 ) ) { 1656285612Sdelphij /* Unexpected reply length */ 1657285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH, 1658285612Sdelphij iLen ) ; 1659285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1660285612Sdelphij up->bLineError = TRUE ; 1661285612Sdelphij return JJY_RECEIVE_ERROR ; 1662285612Sdelphij } 1663285612Sdelphij 1664285612Sdelphij if ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND && iLen == 15 ) { 1665285612Sdelphij /* YYMMDDWHHMMSS<BCC1><BCC2> */ 1666285612Sdelphij 1667285612Sdelphij for ( i = ibcc = 0 ; i < 13 ; i ++ ) { 1668285612Sdelphij ibcc ^= pBuf[i] ; 1669106163Sroberto } 1670285612Sdelphij 1671285612Sdelphij ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ; 1672285612Sdelphij ibcc2 = 0x30 | ( ( ibcc ) & 0xF ) ; 1673285612Sdelphij if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) { 1674285612Sdelphij snprintf( sErr, sizeof(sErr)-1, " BCC error : Recv=%02X,%02X / Calc=%02X,%02X ", 1675285612Sdelphij pBuf[13] & 0xFF, pBuf[14] & 0xFF, 1676285612Sdelphij ibcc1, ibcc2 ) ; 1677285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 1678285612Sdelphij sErr ) ; 1679285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1680285612Sdelphij up->bLineError = TRUE ; 1681285612Sdelphij return JJY_RECEIVE_ERROR ; 1682106163Sroberto } 1683182007Sroberto 1684285612Sdelphij } 1685182007Sroberto 1686285612Sdelphij if ( ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND 1687285612Sdelphij && iLen == 15 ) 1688285612Sdelphij || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS 1689285612Sdelphij && iLen == 17 ) 1690285612Sdelphij || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS 1691285612Sdelphij && iLen == 17 ) ) { 1692285612Sdelphij /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */ 1693182007Sroberto 1694285612Sdelphij rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d", 1695285612Sdelphij &up->year, &up->month, &up->day, 1696285612Sdelphij &up->hour, &up->minute, &up->second ) ; 1697285612Sdelphij 1698285612Sdelphij if ( rc != 6 || up->month < 1 || up->month > 12 1699285612Sdelphij || up->day < 1 || up->day > 31 1700285612Sdelphij || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 1701285612Sdelphij /* Invalid date and time */ 1702285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME, 1703285612Sdelphij rc, up->year, up->month, up->day, 1704285612Sdelphij up->hour, up->minute, up->second ) ; 1705285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1706285612Sdelphij up->bLineError = TRUE ; 1707285612Sdelphij return JJY_RECEIVE_ERROR ; 1708285612Sdelphij } 1709285612Sdelphij 1710285612Sdelphij up->year += 2000 ; 1711285612Sdelphij 1712285612Sdelphij if ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS 1713285612Sdelphij || up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ) { 1714285612Sdelphij /* A time stamp comes on every 0.5 second in the mode 2 of the LT-2000. */ 1715285612Sdelphij 1716285612Sdelphij up->msecond = 500 ; 1717285612Sdelphij up->second -- ; 1718285612Sdelphij if ( up->second < 0 ) { 1719285612Sdelphij up->second = 59 ; 1720285612Sdelphij up->minute -- ; 1721285612Sdelphij if ( up->minute < 0 ) { 1722285612Sdelphij up->minute = 59 ; 1723285612Sdelphij up->hour -- ; 1724285612Sdelphij if ( up->hour < 0 ) { 1725285612Sdelphij up->hour = 23 ; 1726285612Sdelphij up->day -- ; 1727285612Sdelphij if ( up->day < 1 ) { 1728285612Sdelphij up->month -- ; 1729285612Sdelphij if ( up->month < 1 ) { 1730285612Sdelphij up->month = 12 ; 1731285612Sdelphij up->year -- ; 1732285612Sdelphij } 1733285612Sdelphij } 1734285612Sdelphij } 1735285612Sdelphij } 1736182007Sroberto } 1737285612Sdelphij 1738285612Sdelphij } 1739285612Sdelphij 1740285612Sdelphij jjy_synctime( peer, pp, up ) ; 1741285612Sdelphij 1742285612Sdelphij 1743285612Sdelphij } 1744285612Sdelphij 1745285612Sdelphij if (up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ) { 1746285612Sdelphij /* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */ 1747285612Sdelphij 1748285612Sdelphij iLen = strlen( ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND ) ; 1749285612Sdelphij if ( write ( pp->io.fd, ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND, iLen ) != iLen ) { 1750285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 1751285612Sdelphij } 1752285612Sdelphij 1753285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND ) ; 1754285612Sdelphij 1755285612Sdelphij } 1756285612Sdelphij 1757285612Sdelphij return JJY_RECEIVE_DONE ; 1758285612Sdelphij 1759285612Sdelphij} 1760285612Sdelphij 1761285612Sdelphij/**************************************************************************************************/ 1762285612Sdelphij 1763285612Sdelphijstatic void 1764285612Sdelphijjjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer ) 1765285612Sdelphij{ 1766285612Sdelphij 1767285612Sdelphij struct refclockproc *pp ; 1768285612Sdelphij struct jjyunit *up ; 1769285612Sdelphij 1770285612Sdelphij char sCmd[2] ; 1771285612Sdelphij 1772285612Sdelphij pp = peer->procptr ; 1773285612Sdelphij up = pp->unitptr ; 1774285612Sdelphij 1775285612Sdelphij up->bLineError = FALSE ; 1776285612Sdelphij 1777285612Sdelphij /* 1778285612Sdelphij * Send "T" or "C" command 1779285612Sdelphij */ 1780285612Sdelphij 1781285612Sdelphij switch ( up->operationmode ) { 1782285612Sdelphij case ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND : 1783285612Sdelphij sCmd[0] = 'T' ; 1784285612Sdelphij break ; 1785285612Sdelphij case ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS : 1786285612Sdelphij case ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS : 1787285612Sdelphij sCmd[0] = 'C' ; 1788285612Sdelphij break ; 1789285612Sdelphij } 1790285612Sdelphij sCmd[1] = 0 ; 1791285612Sdelphij 1792285612Sdelphij if ( write ( pp->io.fd, sCmd, 1 ) != 1 ) { 1793285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 1794285612Sdelphij } 1795285612Sdelphij 1796285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, sCmd ) ; 1797285612Sdelphij 1798285612Sdelphij} 1799285612Sdelphij 1800285612Sdelphij/*################################################################################################*/ 1801285612Sdelphij/*################################################################################################*/ 1802285612Sdelphij/*## ##*/ 1803285612Sdelphij/*## The CITIZEN T.I.C CO., LTD. JJY receiver JJY200 ##*/ 1804285612Sdelphij/*## ##*/ 1805285612Sdelphij/*## server 127.127.40.X mode 4 ##*/ 1806285612Sdelphij/*## ##*/ 1807285612Sdelphij/*################################################################################################*/ 1808285612Sdelphij/*################################################################################################*/ 1809285612Sdelphij/* */ 1810285612Sdelphij/* Command Response Remarks */ 1811285612Sdelphij/* -------------------- ---------------------------------------- ---------------------------- */ 1812285612Sdelphij/* 'XX YY/MM/DD W HH:MM:SS<CR> XX:OK|NG|ER W:0(Mon)-6(Sun) */ 1813285612Sdelphij/* */ 1814285612Sdelphij/*################################################################################################*/ 1815285612Sdelphij 1816285612Sdelphijstatic int 1817285612Sdelphijjjy_start_citizentic_jjy200 ( int unit, struct peer *peer, struct jjyunit *up ) 1818285612Sdelphij{ 1819285612Sdelphij 1820285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: CITIZEN T.I.C CO. LTD. JJY200" ) ; 1821285612Sdelphij 1822285612Sdelphij up->unittype = UNITTYPE_CITIZENTIC_JJY200 ; 1823285612Sdelphij up->linespeed = SPEED232_CITIZENTIC_JJY200 ; 1824285612Sdelphij up->linediscipline = LDISC_CLK ; 1825285612Sdelphij 1826285612Sdelphij return 0 ; 1827285612Sdelphij 1828285612Sdelphij} 1829285612Sdelphij 1830285612Sdelphij/**************************************************************************************************/ 1831285612Sdelphij 1832285612Sdelphijstatic int 1833285612Sdelphijjjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp ) 1834285612Sdelphij{ 1835285612Sdelphij 1836285612Sdelphij struct jjyunit *up ; 1837285612Sdelphij struct refclockproc *pp ; 1838285612Sdelphij struct peer *peer; 1839285612Sdelphij 1840285612Sdelphij char *pBuf, sLog [ 100 ], sMsg [ 16 ] ; 1841285612Sdelphij int iLen ; 1842285612Sdelphij int rc ; 1843285612Sdelphij char cApostrophe, sStatus[3] ; 1844285612Sdelphij int iWeekday ; 1845285612Sdelphij 1846285612Sdelphij /* Initialize pointers */ 1847285612Sdelphij 1848285612Sdelphij peer = rbufp->recv_peer ; 1849285612Sdelphij pp = peer->procptr ; 1850285612Sdelphij up = pp->unitptr ; 1851285612Sdelphij 1852285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 1853285612Sdelphij pBuf = up->sTextBuf ; 1854285612Sdelphij iLen = up->iTextBufLen ; 1855285612Sdelphij } else { 1856285612Sdelphij pBuf = pp->a_lastcode ; 1857285612Sdelphij iLen = pp->lencode ; 1858285612Sdelphij } 1859285612Sdelphij 1860285612Sdelphij DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_citizentic_jjy200", iLen ) ; 1861285612Sdelphij 1862285612Sdelphij /* 1863285612Sdelphij * JJY-200 sends a timestamp every second. 1864285612Sdelphij * So, a timestamp is ignored unless it is right after polled. 1865285612Sdelphij */ 1866285612Sdelphij 1867285612Sdelphij if ( up->iProcessState != JJY_PROCESS_STATE_RECEIVE ) { 1868285612Sdelphij return JJY_RECEIVE_SKIP ; 1869285612Sdelphij } 1870285612Sdelphij 1871285612Sdelphij /* Check reply length */ 1872285612Sdelphij 1873285612Sdelphij if ( iLen != 23 ) { 1874285612Sdelphij /* Unexpected reply length */ 1875285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH, 1876285612Sdelphij iLen ) ; 1877285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1878285612Sdelphij up->bLineError = TRUE ; 1879285612Sdelphij return JJY_RECEIVE_ERROR ; 1880285612Sdelphij } 1881285612Sdelphij 1882285612Sdelphij /* 'XX YY/MM/DD W HH:MM:SS<CR> */ 1883285612Sdelphij 1884285612Sdelphij rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d", 1885285612Sdelphij &cApostrophe, sStatus, 1886285612Sdelphij &up->year, &up->month, &up->day, &iWeekday, 1887285612Sdelphij &up->hour, &up->minute, &up->second ) ; 1888285612Sdelphij sStatus[2] = 0 ; 1889285612Sdelphij 1890285612Sdelphij if ( rc != 9 || cApostrophe != '\'' 1891285612Sdelphij || ( strcmp( sStatus, "OK" ) != 0 1892285612Sdelphij && strcmp( sStatus, "NG" ) != 0 1893285612Sdelphij && strcmp( sStatus, "ER" ) != 0 ) 1894285612Sdelphij || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 1895285612Sdelphij || iWeekday > 6 1896285612Sdelphij || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 1897285612Sdelphij /* Invalid date and time */ 1898285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME, 1899285612Sdelphij rc, up->year, up->month, up->day, 1900285612Sdelphij up->hour, up->minute, up->second ) ; 1901285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 1902285612Sdelphij up->bLineError = TRUE ; 1903285612Sdelphij return JJY_RECEIVE_ERROR ; 1904285612Sdelphij } else if ( strcmp( sStatus, "NG" ) == 0 1905285612Sdelphij || strcmp( sStatus, "ER" ) == 0 ) { 1906285612Sdelphij /* Timestamp is unsure */ 1907285612Sdelphij snprintf( sMsg, sizeof(sMsg)-1, "status=%s", sStatus ) ; 1908285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TIMESTAMP_UNSURE, 1909285612Sdelphij sMsg ) ; 1910285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ; 1911285612Sdelphij return JJY_RECEIVE_SKIP ; 1912285612Sdelphij } 1913285612Sdelphij 1914285612Sdelphij up->year += 2000 ; 1915285612Sdelphij up->msecond = 0 ; 1916285612Sdelphij 1917285612Sdelphij jjy_synctime( peer, pp, up ) ; 1918285612Sdelphij 1919285612Sdelphij return JJY_RECEIVE_DONE ; 1920285612Sdelphij 1921285612Sdelphij} 1922285612Sdelphij 1923285612Sdelphij/**************************************************************************************************/ 1924285612Sdelphij 1925285612Sdelphijstatic void 1926285612Sdelphijjjy_poll_citizentic_jjy200 ( int unit, struct peer *peer ) 1927285612Sdelphij{ 1928285612Sdelphij 1929285612Sdelphij struct refclockproc *pp ; 1930285612Sdelphij struct jjyunit *up ; 1931285612Sdelphij 1932285612Sdelphij pp = peer->procptr ; 1933285612Sdelphij up = pp->unitptr ; 1934285612Sdelphij 1935285612Sdelphij up->bLineError = FALSE ; 1936285612Sdelphij 1937285612Sdelphij} 1938285612Sdelphij 1939285612Sdelphij/*################################################################################################*/ 1940285612Sdelphij/*################################################################################################*/ 1941285612Sdelphij/*## ##*/ 1942285612Sdelphij/*## The Tristate Ltd. GPS clock TS-GPS01 ##*/ 1943285612Sdelphij/*## ##*/ 1944285612Sdelphij/*## server 127.127.40.X mode 5 ##*/ 1945285612Sdelphij/*## ##*/ 1946285612Sdelphij/*################################################################################################*/ 1947285612Sdelphij/*################################################################################################*/ 1948285612Sdelphij/* */ 1949285612Sdelphij/* This clock has NMEA mode and command/respose mode. */ 1950285612Sdelphij/* When this jjy driver are used, set to command/respose mode of this clock */ 1951285612Sdelphij/* by the onboard switch SW4, and make sure the LED-Y is tured on. */ 1952285612Sdelphij/* Other than this JJY driver, the refclock driver type 20, generic NMEA driver, */ 1953285612Sdelphij/* works with the NMEA mode of this clock. */ 1954285612Sdelphij/* */ 1955285612Sdelphij/* Command Response Remarks */ 1956285612Sdelphij/* -------------------- ---------------------------------------- ---------------------------- */ 1957285612Sdelphij/* stus<CR><LF> *R|*G|*U|+U<CR><LF> */ 1958285612Sdelphij/* date<CR><LF> YY/MM/DD<CR><LF> */ 1959285612Sdelphij/* time<CR><LF> HH:MM:SS<CR><LF> */ 1960285612Sdelphij/* */ 1961285612Sdelphij/*################################################################################################*/ 1962285612Sdelphij 1963285612Sdelphij#define TS_GPS01_COMMAND_NUMBER_DATE 1 1964285612Sdelphij#define TS_GPS01_COMMAND_NUMBER_TIME 2 1965285612Sdelphij#define TS_GPS01_COMMAND_NUMBER_STUS 4 1966285612Sdelphij 1967285612Sdelphij#define TS_GPS01_REPLY_DATE "yyyy/mm/dd" 1968285612Sdelphij#define TS_GPS01_REPLY_TIME "hh:mm:ss" 1969285612Sdelphij#define TS_GPS01_REPLY_STUS_RTC "*R" 1970285612Sdelphij#define TS_GPS01_REPLY_STUS_GPS "*G" 1971285612Sdelphij#define TS_GPS01_REPLY_STUS_UTC "*U" 1972285612Sdelphij#define TS_GPS01_REPLY_STUS_PPS "+U" 1973285612Sdelphij 1974285612Sdelphij#define TS_GPS01_REPLY_LENGTH_DATE 10 /* Length without <CR><LF> */ 1975285612Sdelphij#define TS_GPS01_REPLY_LENGTH_TIME 8 /* Length without <CR><LF> */ 1976285612Sdelphij#define TS_GPS01_REPLY_LENGTH_STUS 2 /* Length without <CR><LF> */ 1977285612Sdelphij 1978285612Sdelphijstatic struct 1979285612Sdelphij{ 1980285612Sdelphij char commandNumber ; 1981285612Sdelphij const char *command ; 1982285612Sdelphij int commandLength ; 1983285612Sdelphij int iExpectedReplyLength ; 1984285612Sdelphij} tristate_gps01_command_sequence[] = 1985285612Sdelphij{ 1986285612Sdelphij { 0, NULL, 0, 0 }, /* Idle */ 1987285612Sdelphij { TS_GPS01_COMMAND_NUMBER_STUS, "stus\r\n", 6, TS_GPS01_REPLY_LENGTH_STUS }, 1988285612Sdelphij { TS_GPS01_COMMAND_NUMBER_TIME, "time\r\n", 6, TS_GPS01_REPLY_LENGTH_TIME }, 1989285612Sdelphij { TS_GPS01_COMMAND_NUMBER_DATE, "date\r\n", 6, TS_GPS01_REPLY_LENGTH_DATE }, 1990285612Sdelphij { TS_GPS01_COMMAND_NUMBER_TIME, "time\r\n", 6, TS_GPS01_REPLY_LENGTH_TIME }, 1991285612Sdelphij /* End of command */ 1992285612Sdelphij { 0, NULL, 0, 0 } 1993285612Sdelphij} ; 1994285612Sdelphij 1995285612Sdelphij/**************************************************************************************************/ 1996285612Sdelphij 1997285612Sdelphijstatic int 1998285612Sdelphijjjy_start_tristate_gpsclock01 ( int unit, struct peer *peer, struct jjyunit *up ) 1999285612Sdelphij{ 2000285612Sdelphij 2001285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Tristate Ltd. TS-GPS01" ) ; 2002285612Sdelphij 2003285612Sdelphij up->unittype = UNITTYPE_TRISTATE_GPSCLOCK01 ; 2004285612Sdelphij up->linespeed = SPEED232_TRISTATE_GPSCLOCK01 ; 2005285612Sdelphij up->linediscipline = LDISC_CLK ; 2006285612Sdelphij 2007285612Sdelphij return 0 ; 2008285612Sdelphij 2009285612Sdelphij} 2010285612Sdelphij 2011285612Sdelphij/**************************************************************************************************/ 2012285612Sdelphij 2013285612Sdelphijstatic int 2014285612Sdelphijjjy_receive_tristate_gpsclock01 ( struct recvbuf *rbufp ) 2015285612Sdelphij{ 2016182007Sroberto#ifdef DEBUG 2017285612Sdelphij static const char *sFunctionName = "jjy_receive_tristate_gpsclock01" ; 2018182007Sroberto#endif 2019182007Sroberto 2020285612Sdelphij struct jjyunit *up ; 2021285612Sdelphij struct refclockproc *pp ; 2022285612Sdelphij struct peer *peer; 2023106163Sroberto 2024294569Sdelphij char * pBuf ; 2025294569Sdelphij char sLog [ 100 ] ; 2026294569Sdelphij int iLen ; 2027294569Sdelphij int rc ; 2028106163Sroberto 2029294569Sdelphij const char * pCmd ; 2030294569Sdelphij int iCmdLen ; 2031285612Sdelphij 2032285612Sdelphij /* Initialize pointers */ 2033285612Sdelphij 2034285612Sdelphij peer = rbufp->recv_peer ; 2035285612Sdelphij pp = peer->procptr ; 2036285612Sdelphij up = pp->unitptr ; 2037285612Sdelphij 2038285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 2039285612Sdelphij pBuf = up->sTextBuf ; 2040285612Sdelphij iLen = up->iTextBufLen ; 2041285612Sdelphij } else { 2042285612Sdelphij pBuf = pp->a_lastcode ; 2043285612Sdelphij iLen = pp->lencode ; 2044285612Sdelphij } 2045285612Sdelphij 2046285612Sdelphij DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_tristate_gpsclock01", iLen ) ; 2047285612Sdelphij 2048285612Sdelphij /* Ignore NMEA data stream */ 2049285612Sdelphij 2050285612Sdelphij if ( iLen > 5 2051285612Sdelphij && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) { 2052182007Sroberto#ifdef DEBUG 2053285612Sdelphij if ( debug ) { 2054285612Sdelphij printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n", 2055285612Sdelphij sFunctionName, pBuf ) ; 2056285612Sdelphij } 2057182007Sroberto#endif 2058285612Sdelphij return JJY_RECEIVE_WAIT ; 2059285612Sdelphij } 2060285612Sdelphij 2061285612Sdelphij /* 2062285612Sdelphij * Skip command prompt '$Cmd>' from the TS-GPSclock-01 2063285612Sdelphij */ 2064285612Sdelphij if ( iLen == 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) { 2065285612Sdelphij return JJY_RECEIVE_WAIT ; 2066285612Sdelphij } else if ( iLen > 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) { 2067285612Sdelphij pBuf += 5 ; 2068285612Sdelphij iLen -= 5 ; 2069285612Sdelphij } 2070285612Sdelphij 2071285612Sdelphij /* 2072285612Sdelphij * Ignore NMEA data stream after command prompt 2073285612Sdelphij */ 2074285612Sdelphij if ( iLen > 5 2075285612Sdelphij && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) { 2076285612Sdelphij#ifdef DEBUG 2077285612Sdelphij if ( debug ) { 2078285612Sdelphij printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n", 2079285612Sdelphij sFunctionName, pBuf ) ; 2080106163Sroberto } 2081182007Sroberto#endif 2082285612Sdelphij return JJY_RECEIVE_WAIT ; 2083285612Sdelphij } 2084285612Sdelphij 2085285612Sdelphij /* Check expected reply */ 2086285612Sdelphij 2087285612Sdelphij if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) { 2088285612Sdelphij /* Command sequence has not been started, or has been completed */ 2089285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY, 2090285612Sdelphij pBuf ) ; 2091285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2092285612Sdelphij up->bLineError = TRUE ; 2093285612Sdelphij return JJY_RECEIVE_ERROR ; 2094285612Sdelphij } 2095285612Sdelphij 2096285612Sdelphij /* Check reply length */ 2097285612Sdelphij 2098285612Sdelphij if ( iLen != tristate_gps01_command_sequence[up->iCommandSeq].iExpectedReplyLength ) { 2099285612Sdelphij /* Unexpected reply length */ 2100285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH, 2101285612Sdelphij iLen ) ; 2102285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2103285612Sdelphij up->bLineError = TRUE ; 2104285612Sdelphij return JJY_RECEIVE_ERROR ; 2105285612Sdelphij } 2106285612Sdelphij 2107285612Sdelphij /* Parse reply */ 2108285612Sdelphij 2109285612Sdelphij switch ( tristate_gps01_command_sequence[up->iCommandSeq].commandNumber ) { 2110285612Sdelphij 2111285612Sdelphij case TS_GPS01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD */ 2112285612Sdelphij 2113285612Sdelphij rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ; 2114285612Sdelphij 2115285612Sdelphij if ( rc != 3 || up->year < 2000 || 2099 <= up->year 2116285612Sdelphij || up->month < 1 || 12 < up->month 2117285612Sdelphij || up->day < 1 || 31 < up->day ) { 2118285612Sdelphij /* Invalid date */ 2119285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE, 2120285612Sdelphij rc, up->year, up->month, up->day ) ; 2121285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2122285612Sdelphij up->bLineError = TRUE ; 2123285612Sdelphij return JJY_RECEIVE_ERROR ; 2124106163Sroberto } 2125285612Sdelphij 2126285612Sdelphij break ; 2127285612Sdelphij 2128285612Sdelphij case TS_GPS01_COMMAND_NUMBER_TIME : /* HH:MM:SS */ 2129285612Sdelphij 2130285612Sdelphij if ( up->iTimestampCount >= 2 ) { 2131285612Sdelphij /* Too many time reply */ 2132285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY, 2133285612Sdelphij up->iTimestampCount ) ; 2134285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2135285612Sdelphij up->bLineError = TRUE ; 2136285612Sdelphij return JJY_RECEIVE_ERROR ; 2137285612Sdelphij } 2138285612Sdelphij 2139285612Sdelphij rc = sscanf ( pBuf, "%2d:%2d:%2d", 2140285612Sdelphij &up->hour, &up->minute, &up->second ) ; 2141285612Sdelphij 2142285612Sdelphij if ( rc != 3 2143285612Sdelphij || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 2144285612Sdelphij /* Invalid time */ 2145285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME, 2146285612Sdelphij rc, up->hour, up->minute, up->second ) ; 2147285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2148285612Sdelphij up->bLineError = TRUE ; 2149285612Sdelphij return JJY_RECEIVE_ERROR ; 2150285612Sdelphij } 2151285612Sdelphij 2152285612Sdelphij up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ; 2153285612Sdelphij 2154285612Sdelphij up->iTimestampCount++ ; 2155285612Sdelphij 2156106163Sroberto up->msecond = 0 ; 2157285612Sdelphij 2158285612Sdelphij break ; 2159285612Sdelphij 2160285612Sdelphij case TS_GPS01_COMMAND_NUMBER_STUS : 2161285612Sdelphij 2162285612Sdelphij if ( strncmp( pBuf, TS_GPS01_REPLY_STUS_RTC, TS_GPS01_REPLY_LENGTH_STUS ) == 0 2163285612Sdelphij || strncmp( pBuf, TS_GPS01_REPLY_STUS_GPS, TS_GPS01_REPLY_LENGTH_STUS ) == 0 2164285612Sdelphij || strncmp( pBuf, TS_GPS01_REPLY_STUS_UTC, TS_GPS01_REPLY_LENGTH_STUS ) == 0 2165285612Sdelphij || strncmp( pBuf, TS_GPS01_REPLY_STUS_PPS, TS_GPS01_REPLY_LENGTH_STUS ) == 0 ) { 2166285612Sdelphij /* Good */ 2167285612Sdelphij } else { 2168285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 2169285612Sdelphij pBuf ) ; 2170285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2171285612Sdelphij up->bLineError = TRUE ; 2172285612Sdelphij return JJY_RECEIVE_ERROR ; 2173106163Sroberto } 2174285612Sdelphij 2175106163Sroberto break ; 2176106163Sroberto 2177106163Sroberto default : /* Unexpected reply */ 2178106163Sroberto 2179285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 2180285612Sdelphij pBuf ) ; 2181285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2182285612Sdelphij up->bLineError = TRUE ; 2183285612Sdelphij return JJY_RECEIVE_ERROR ; 2184106163Sroberto 2185106163Sroberto } 2186106163Sroberto 2187285612Sdelphij if ( up->iTimestampCount == 2 ) { 2188285612Sdelphij /* Process date and time */ 2189106163Sroberto 2190285612Sdelphij if ( up->iTimestamp[1] - 2 <= up->iTimestamp[0] 2191285612Sdelphij && up->iTimestamp[0] <= up->iTimestamp[1] ) { 2192285612Sdelphij /* 3 commands (time,date,stim) was excuted in two seconds */ 2193285612Sdelphij jjy_synctime( peer, pp, up ) ; 2194285612Sdelphij return JJY_RECEIVE_DONE ; 2195285612Sdelphij } else if ( up->iTimestamp[0] > up->iTimestamp[1] ) { 2196285612Sdelphij /* Over midnight, and date is unsure */ 2197285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2, 2198285612Sdelphij up->iTimestamp[0], up->iTimestamp[1] ) ; 2199285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ; 2200285612Sdelphij return JJY_RECEIVE_SKIP ; 2201285612Sdelphij } else { 2202285612Sdelphij /* Slow reply */ 2203285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2, 2204285612Sdelphij up->iTimestamp[0], up->iTimestamp[1] ) ; 2205285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2206285612Sdelphij up->bLineError = TRUE ; 2207285612Sdelphij return JJY_RECEIVE_ERROR ; 2208285612Sdelphij } 2209285612Sdelphij 2210285612Sdelphij } 2211285612Sdelphij 2212285612Sdelphij if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) { 2213285612Sdelphij /* Command sequence completed */ 2214285612Sdelphij jjy_synctime( peer, pp, up ) ; 2215285612Sdelphij return JJY_RECEIVE_DONE ; 2216285612Sdelphij } 2217285612Sdelphij 2218285612Sdelphij /* Issue next command */ 2219285612Sdelphij 2220285612Sdelphij if ( tristate_gps01_command_sequence[up->iCommandSeq].command != NULL ) { 2221285612Sdelphij up->iCommandSeq ++ ; 2222285612Sdelphij } 2223285612Sdelphij 2224285612Sdelphij if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) { 2225285612Sdelphij /* Command sequence completed */ 2226285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_DONE ; 2227285612Sdelphij return JJY_RECEIVE_DONE ; 2228285612Sdelphij } 2229285612Sdelphij 2230285612Sdelphij pCmd = tristate_gps01_command_sequence[up->iCommandSeq].command ; 2231285612Sdelphij iCmdLen = tristate_gps01_command_sequence[up->iCommandSeq].commandLength ; 2232285612Sdelphij if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 2233285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 2234285612Sdelphij } 2235285612Sdelphij 2236285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 2237285612Sdelphij 2238285612Sdelphij return JJY_RECEIVE_WAIT ; 2239285612Sdelphij 2240106163Sroberto} 2241106163Sroberto 2242106163Sroberto/**************************************************************************************************/ 2243106163Sroberto 2244285612Sdelphijstatic void 2245285612Sdelphijjjy_poll_tristate_gpsclock01 ( int unit, struct peer *peer ) 2246106163Sroberto{ 2247285612Sdelphij#ifdef DEBUG 2248285612Sdelphij static const char *sFunctionName = "jjy_poll_tristate_gpsclock01" ; 2249285612Sdelphij#endif 2250106163Sroberto 2251106163Sroberto struct refclockproc *pp ; 2252285612Sdelphij struct jjyunit *up ; 2253106163Sroberto 2254294569Sdelphij const char * pCmd ; 2255294569Sdelphij int iCmdLen ; 2256106163Sroberto 2257285612Sdelphij pp = peer->procptr ; 2258285612Sdelphij up = pp->unitptr ; 2259285612Sdelphij 2260285612Sdelphij up->iTimestampCount = 0 ; 2261285612Sdelphij 2262285612Sdelphij if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) { 2263285612Sdelphij /* Skip "stus" command */ 2264285612Sdelphij up->iCommandSeq = 1 ; 2265285612Sdelphij up->iLineCount = 1 ; 2266285612Sdelphij } 2267285612Sdelphij 2268285612Sdelphij#ifdef DEBUG 2269285612Sdelphij if ( debug ) { 2270285612Sdelphij printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->iLineCount=%d\n", 2271285612Sdelphij sFunctionName, pp->sloppyclockflag, CLK_FLAG1, 2272285612Sdelphij up->iLineCount ) ; 2273285612Sdelphij } 2274285612Sdelphij#endif 2275285612Sdelphij 2276106163Sroberto /* 2277285612Sdelphij * Send a first command 2278106163Sroberto */ 2279285612Sdelphij 2280285612Sdelphij up->iCommandSeq ++ ; 2281285612Sdelphij 2282285612Sdelphij pCmd = tristate_gps01_command_sequence[up->iCommandSeq].command ; 2283285612Sdelphij iCmdLen = tristate_gps01_command_sequence[up->iCommandSeq].commandLength ; 2284285612Sdelphij if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 2285285612Sdelphij refclock_report ( peer, CEVNT_FAULT ) ; 2286285612Sdelphij } 2287285612Sdelphij 2288285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 2289285612Sdelphij 2290285612Sdelphij} 2291285612Sdelphij 2292285612Sdelphij/*################################################################################################*/ 2293285612Sdelphij/*################################################################################################*/ 2294285612Sdelphij/*## ##*/ 2295285612Sdelphij/*## The SEIKO TIME SYSTEMS TDC-300 ##*/ 2296285612Sdelphij/*## ##*/ 2297285612Sdelphij/*## server 127.127.40.X mode 6 ##*/ 2298285612Sdelphij/*## ##*/ 2299285612Sdelphij/*################################################################################################*/ 2300285612Sdelphij/*################################################################################################*/ 2301285612Sdelphij/* */ 2302285612Sdelphij/* Type Response Remarks */ 2303285612Sdelphij/* -------------------- ---------------------------------------- ---------------------------- */ 2304285612Sdelphij/* Type 1 <STX>HH:MM:SS<ETX> */ 2305285612Sdelphij/* Type 2 <STX>YYMMDDHHMMSSWLSCU<ETX> W:0(Sun)-6(Sat) */ 2306285612Sdelphij/* Type 3 <STX>YYMMDDWHHMMSS<ETX> W:0(Sun)-6(Sat) */ 2307285612Sdelphij/* <STX><xE5><ETX> 5 to 10 mSec. before second */ 2308285612Sdelphij/* */ 2309285612Sdelphij/*################################################################################################*/ 2310285612Sdelphij 2311285612Sdelphijstatic struct jjyRawDataBreak seiko_tsys_tdc_300_raw_break [ ] = 2312285612Sdelphij{ 2313285612Sdelphij { "\x03", 1 }, { NULL, 0 } 2314285612Sdelphij} ; 2315285612Sdelphij 2316285612Sdelphij/**************************************************************************************************/ 2317285612Sdelphij 2318285612Sdelphijstatic int 2319285612Sdelphijjjy_start_seiko_tsys_tdc_300 ( int unit, struct peer *peer, struct jjyunit *up ) 2320285612Sdelphij{ 2321285612Sdelphij 2322285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: SEIKO TIME SYSTEMS TDC-300" ) ; 2323285612Sdelphij 2324285612Sdelphij up->unittype = UNITTYPE_SEIKO_TIMESYS_TDC_300 ; 2325285612Sdelphij up->linespeed = SPEED232_SEIKO_TIMESYS_TDC_300 ; 2326285612Sdelphij up->linediscipline = LDISC_RAW ; 2327285612Sdelphij 2328285612Sdelphij up->pRawBreak = seiko_tsys_tdc_300_raw_break ; 2329285612Sdelphij up->bWaitBreakString = TRUE ; 2330285612Sdelphij 2331285612Sdelphij up->bSkipCntrlCharOnly = FALSE ; 2332285612Sdelphij 2333285612Sdelphij return 0 ; 2334285612Sdelphij 2335285612Sdelphij} 2336285612Sdelphij 2337285612Sdelphij/**************************************************************************************************/ 2338285612Sdelphij 2339285612Sdelphijstatic int 2340285612Sdelphijjjy_receive_seiko_tsys_tdc_300 ( struct recvbuf *rbufp ) 2341285612Sdelphij{ 2342285612Sdelphij 2343285612Sdelphij struct peer *peer; 2344285612Sdelphij struct refclockproc *pp ; 2345285612Sdelphij struct jjyunit *up ; 2346285612Sdelphij 2347285612Sdelphij char *pBuf, sLog [ 100 ] ; 2348285612Sdelphij int iLen, i ; 2349285612Sdelphij int rc, iWeekday ; 2350285612Sdelphij time_t now ; 2351285612Sdelphij struct tm *pTime ; 2352285612Sdelphij 2353285612Sdelphij /* Initialize pointers */ 2354285612Sdelphij 2355285612Sdelphij peer = rbufp->recv_peer ; 2356106163Sroberto pp = peer->procptr ; 2357285612Sdelphij up = pp->unitptr ; 2358106163Sroberto 2359106163Sroberto if ( up->linediscipline == LDISC_RAW ) { 2360285612Sdelphij pBuf = up->sTextBuf ; 2361285612Sdelphij iLen = up->iTextBufLen ; 2362106163Sroberto } else { 2363285612Sdelphij pBuf = pp->a_lastcode ; 2364285612Sdelphij iLen = pp->lencode ; 2365106163Sroberto } 2366106163Sroberto 2367285612Sdelphij DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_seiko_tsys_tdc_300", iLen ) ; 2368106163Sroberto 2369285612Sdelphij /* 2370285612Sdelphij * TDC-300 sends a timestamp every second. 2371285612Sdelphij * So, a timestamp is ignored unless it is right after polled. 2372285612Sdelphij */ 2373106163Sroberto 2374285612Sdelphij if ( up->iProcessState != JJY_PROCESS_STATE_RECEIVE ) { 2375285612Sdelphij return JJY_RECEIVE_SKIP ; 2376285612Sdelphij } 2377285612Sdelphij 2378285612Sdelphij /* Process timestamp */ 2379285612Sdelphij 2380285612Sdelphij up->iReceiveSeq ++ ; 2381285612Sdelphij 2382285612Sdelphij switch ( iLen ) { 2383285612Sdelphij 2384285612Sdelphij case 8 : /* Type 1 : <STX>HH:MM:SS<ETX> */ 2385285612Sdelphij 2386285612Sdelphij for ( i = 0 ; i < iLen ; i ++ ) { 2387285612Sdelphij pBuf[i] &= 0x7F ; 2388106163Sroberto } 2389285612Sdelphij 2390285612Sdelphij rc = sscanf ( pBuf+1, "%2d:%2d:%2d", 2391285612Sdelphij &up->hour, &up->minute, &up->second ) ; 2392285612Sdelphij 2393285612Sdelphij if ( rc != 3 2394106163Sroberto || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 2395285612Sdelphij /* Invalid time */ 2396285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME, 2397285612Sdelphij rc, up->hour, up->minute, up->second ) ; 2398285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2399285612Sdelphij up->bLineError = TRUE ; 2400285612Sdelphij return JJY_RECEIVE_ERROR ; 2401285612Sdelphij } else if ( up->hour == 23 && up->minute == 59 && up->second >= 55 ) { 2402285612Sdelphij /* Uncertainty date guard */ 2403285612Sdelphij return JJY_RECEIVE_WAIT ; 2404106163Sroberto } 2405285612Sdelphij 2406285612Sdelphij time( &now ) ; 2407285612Sdelphij pTime = localtime( &now ) ; 2408285612Sdelphij up->year = pTime->tm_year ; 2409285612Sdelphij up->month = pTime->tm_mon + 1 ; 2410285612Sdelphij up->day = pTime->tm_mday ; 2411285612Sdelphij 2412106163Sroberto break ; 2413106163Sroberto 2414285612Sdelphij case 17 : /* Type 2 : <STX>YYMMDDHHMMSSWLSCU<ETX> */ 2415106163Sroberto 2416285612Sdelphij for ( i = 0 ; i < iLen ; i ++ ) { 2417285612Sdelphij pBuf[i] &= 0x7F ; 2418285612Sdelphij } 2419285612Sdelphij 2420285612Sdelphij rc = sscanf ( pBuf+1, "%2d%2d%2d%2d%2d%2d%1d", 2421285612Sdelphij &up->year, &up->month, &up->day, 2422285612Sdelphij &up->hour, &up->minute, &up->second, &iWeekday ) ; 2423285612Sdelphij 2424285612Sdelphij if ( rc != 7 2425285612Sdelphij || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 2426285612Sdelphij || iWeekday > 6 2427285612Sdelphij || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 2428285612Sdelphij /* Invalid date and time */ 2429285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME, 2430285612Sdelphij rc, up->year, up->month, up->day, 2431285612Sdelphij up->hour, up->minute, up->second ) ; 2432285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2433285612Sdelphij up->bLineError = TRUE ; 2434285612Sdelphij return JJY_RECEIVE_ERROR ; 2435285612Sdelphij } 2436285612Sdelphij 2437106163Sroberto break ; 2438106163Sroberto 2439285612Sdelphij case 13 : /* Type 3 : <STX>YYMMDDWHHMMSS<ETX> */ 2440285612Sdelphij 2441285612Sdelphij rc = sscanf ( pBuf, "%2d%2d%2d%1d%2d%2d%2d", 2442285612Sdelphij &up->year, &up->month, &up->day, &iWeekday, 2443285612Sdelphij &up->hour, &up->minute, &up->second ) ; 2444285612Sdelphij 2445285612Sdelphij if ( rc != 7 2446285612Sdelphij || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 2447285612Sdelphij || iWeekday > 6 2448285612Sdelphij || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 2449285612Sdelphij /* Invalid date and time */ 2450285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME, 2451285612Sdelphij rc, up->year, up->month, up->day, 2452285612Sdelphij up->hour, up->minute, up->second ) ; 2453285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2454285612Sdelphij up->bLineError = TRUE ; 2455285612Sdelphij return JJY_RECEIVE_ERROR ; 2456285612Sdelphij } 2457285612Sdelphij 2458285612Sdelphij return JJY_RECEIVE_WAIT ; 2459285612Sdelphij 2460285612Sdelphij case 1 : /* Type 3 : <STX><xE5><ETX> */ 2461285612Sdelphij 2462285612Sdelphij if ( ( *pBuf & 0xFF ) != 0xE5 ) { 2463285612Sdelphij /* Invalid second signal */ 2464285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY, 2465285612Sdelphij up->sLineBuf ) ; 2466285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2467285612Sdelphij up->bLineError = TRUE ; 2468285612Sdelphij return JJY_RECEIVE_ERROR ; 2469285612Sdelphij } else if ( up->iReceiveSeq == 1 ) { 2470285612Sdelphij /* Wait for next timestamp */ 2471285612Sdelphij up->iReceiveSeq -- ; 2472285612Sdelphij return JJY_RECEIVE_WAIT ; 2473285612Sdelphij } else if ( up->iReceiveSeq >= 3 ) { 2474285612Sdelphij /* Unexpected second signal */ 2475285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY, 2476285612Sdelphij up->sLineBuf ) ; 2477285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2478285612Sdelphij up->bLineError = TRUE ; 2479285612Sdelphij return JJY_RECEIVE_ERROR ; 2480285612Sdelphij } 2481285612Sdelphij 2482285612Sdelphij break ; 2483285612Sdelphij 2484285612Sdelphij default : /* Unexpected reply length */ 2485285612Sdelphij 2486285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH, 2487285612Sdelphij iLen ) ; 2488285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 2489285612Sdelphij up->bLineError = TRUE ; 2490285612Sdelphij return JJY_RECEIVE_ERROR ; 2491285612Sdelphij 2492106163Sroberto } 2493106163Sroberto 2494285612Sdelphij up->year += 2000 ; 2495285612Sdelphij up->msecond = 0 ; 2496106163Sroberto 2497285612Sdelphij jjy_synctime( peer, pp, up ) ; 2498285612Sdelphij 2499285612Sdelphij return JJY_RECEIVE_DONE ; 2500285612Sdelphij 2501106163Sroberto} 2502106163Sroberto 2503106163Sroberto/**************************************************************************************************/ 2504182007Sroberto 2505285612Sdelphijstatic void 2506285612Sdelphijjjy_poll_seiko_tsys_tdc_300 ( int unit, struct peer *peer ) 2507285612Sdelphij{ 2508285612Sdelphij 2509285612Sdelphij struct refclockproc *pp ; 2510285612Sdelphij struct jjyunit *up ; 2511285612Sdelphij 2512285612Sdelphij pp = peer->procptr ; 2513285612Sdelphij up = pp->unitptr ; 2514285612Sdelphij 2515285612Sdelphij up->bLineError = FALSE ; 2516285612Sdelphij 2517285612Sdelphij} 2518285612Sdelphij 2519285612Sdelphij/*################################################################################################*/ 2520285612Sdelphij/*################################################################################################*/ 2521285612Sdelphij/*## ##*/ 2522285612Sdelphij/*## Telephone JJY ##*/ 2523285612Sdelphij/*## ##*/ 2524285612Sdelphij/*## server 127.127.40.X mode 100 to 180 ##*/ 2525285612Sdelphij/*## ##*/ 2526285612Sdelphij/*################################################################################################*/ 2527285612Sdelphij/*################################################################################################*/ 2528285612Sdelphij/* */ 2529285612Sdelphij/* Prompt Command Response Remarks */ 2530285612Sdelphij/* -------------------- -------------------- -------------------- -------------------------- */ 2531285612Sdelphij/* Name<SP>?<SP> TJJY<CR> Welcome messages TJJY is a guest user ID */ 2532285612Sdelphij/* > 4DATE<CR> YYYYMMDD<CR> */ 2533285612Sdelphij/* > LEAPSEC<CR> XX<CR> One of <SP>0, +1, -1 */ 2534285612Sdelphij/* > TIME<CR> HHMMSS<CR> 3 times on second */ 2535285612Sdelphij/* > BYE<CR> Sayounara messages */ 2536285612Sdelphij/* */ 2537285612Sdelphij/*################################################################################################*/ 2538285612Sdelphij 2539285612Sdelphijstatic struct jjyRawDataBreak teljjy_raw_break [ ] = 2540285612Sdelphij{ 2541285612Sdelphij { "\r\n", 2 }, 2542285612Sdelphij { "\r" , 1 }, 2543285612Sdelphij { "\n" , 1 }, 2544285612Sdelphij { "Name ? ", 7 }, 2545285612Sdelphij { ">" , 1 }, 2546285612Sdelphij { "+++" , 3 }, 2547285612Sdelphij { NULL , 0 } 2548285612Sdelphij} ; 2549285612Sdelphij 2550285612Sdelphij#define TELJJY_STATE_IDLE 0 2551285612Sdelphij#define TELJJY_STATE_DAILOUT 1 2552285612Sdelphij#define TELJJY_STATE_LOGIN 2 2553285612Sdelphij#define TELJJY_STATE_CONNECT 3 2554285612Sdelphij#define TELJJY_STATE_BYE 4 2555285612Sdelphij 2556285612Sdelphij#define TELJJY_EVENT_NULL 0 2557285612Sdelphij#define TELJJY_EVENT_START 1 2558285612Sdelphij#define TELJJY_EVENT_CONNECT 2 2559285612Sdelphij#define TELJJY_EVENT_DISCONNECT 3 2560285612Sdelphij#define TELJJY_EVENT_COMMAND 4 2561285612Sdelphij#define TELJJY_EVENT_LOGIN 5 /* Posted by the jjy_receive_telephone */ 2562285612Sdelphij#define TELJJY_EVENT_PROMPT 6 /* Posted by the jjy_receive_telephone */ 2563285612Sdelphij#define TELJJY_EVENT_DATA 7 /* Posted by the jjy_receive_telephone */ 2564285612Sdelphij#define TELJJY_EVENT_ERROR 8 /* Posted by the jjy_receive_telephone */ 2565285612Sdelphij#define TELJJY_EVENT_SILENT 9 /* Posted by the jjy_timer_telephone */ 2566285612Sdelphij#define TELJJY_EVENT_TIMEOUT 10 /* Posted by the jjy_timer_telephone */ 2567285612Sdelphij 2568285612Sdelphijstatic void teljjy_control ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2569285612Sdelphij 2570285612Sdelphijstatic int teljjy_idle_ignore ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2571285612Sdelphijstatic int teljjy_idle_dialout ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2572285612Sdelphijstatic int teljjy_dial_ignore ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2573285612Sdelphijstatic int teljjy_dial_login ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2574285612Sdelphijstatic int teljjy_dial_disc ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2575285612Sdelphijstatic int teljjy_login_ignore ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2576285612Sdelphijstatic int teljjy_login_disc ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2577285612Sdelphijstatic int teljjy_login_conn ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2578285612Sdelphijstatic int teljjy_login_login ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2579285612Sdelphijstatic int teljjy_login_silent ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2580285612Sdelphijstatic int teljjy_login_error ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2581285612Sdelphijstatic int teljjy_conn_ignore ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2582285612Sdelphijstatic int teljjy_conn_disc ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2583285612Sdelphijstatic int teljjy_conn_send ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2584285612Sdelphijstatic int teljjy_conn_data ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2585285612Sdelphijstatic int teljjy_conn_silent ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2586285612Sdelphijstatic int teljjy_conn_error ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2587285612Sdelphijstatic int teljjy_bye_ignore ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2588285612Sdelphijstatic int teljjy_bye_disc ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2589285612Sdelphijstatic int teljjy_bye_modem ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ; 2590285612Sdelphij 2591294569Sdelphijstatic int ( *pTeljjyHandler [ ] [ 5 ] ) ( struct peer *, struct refclockproc *, struct jjyunit *) = 2592285612Sdelphij{ /*STATE_IDLE STATE_DAILOUT STATE_LOGIN STATE_CONNECT STATE_BYE */ 2593285612Sdelphij/* NULL */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore }, 2594285612Sdelphij/* START */ { teljjy_idle_dialout, teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore }, 2595285612Sdelphij/* CONNECT */ { teljjy_idle_ignore , teljjy_dial_login , teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore }, 2596285612Sdelphij/* DISCONNECT */ { teljjy_idle_ignore , teljjy_dial_disc , teljjy_login_disc , teljjy_conn_disc , teljjy_bye_disc }, 2597285612Sdelphij/* COMMAND */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_modem }, 2598285612Sdelphij/* LOGIN */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_login , teljjy_conn_error , teljjy_bye_ignore }, 2599285612Sdelphij/* PROMPT */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_conn , teljjy_conn_send , teljjy_bye_ignore }, 2600285612Sdelphij/* DATA */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_data , teljjy_bye_ignore }, 2601285612Sdelphij/* ERROR */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_error , teljjy_conn_error , teljjy_bye_ignore }, 2602285612Sdelphij/* SILENT */ { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_silent, teljjy_conn_silent, teljjy_bye_ignore }, 2603285612Sdelphij/* TIMEOUT */ { teljjy_idle_ignore , teljjy_dial_disc , teljjy_login_error , teljjy_conn_error , teljjy_bye_modem } 2604285612Sdelphij} ; 2605285612Sdelphij 2606285612Sdelphijstatic short iTeljjyNextState [ ] [ 5 ] = 2607285612Sdelphij{ /*STATE_IDLE STATE_DAILOUT STATE_LOGIN STATE_CONNECT STATE_BYE */ 2608285612Sdelphij/* NULL */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE }, 2609285612Sdelphij/* START */ { TELJJY_STATE_DAILOUT, TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE }, 2610285612Sdelphij/* CONNECT */ { TELJJY_STATE_IDLE , TELJJY_STATE_LOGIN , TELJJY_STATE_LOGIN , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE }, 2611285612Sdelphij/* DISCONNECT */ { TELJJY_STATE_IDLE , TELJJY_STATE_IDLE , TELJJY_STATE_IDLE , TELJJY_STATE_IDLE , TELJJY_STATE_IDLE }, 2612285612Sdelphij/* COMMAND */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE }, 2613285612Sdelphij/* LOGIN */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN , TELJJY_STATE_BYE , TELJJY_STATE_BYE }, 2614285612Sdelphij/* PROMPT */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_CONNECT, TELJJY_STATE_BYE , TELJJY_STATE_BYE }, 2615285612Sdelphij/* DATA */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE }, 2616285612Sdelphij/* ERROR */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_BYE , TELJJY_STATE_BYE , TELJJY_STATE_BYE }, 2617285612Sdelphij/* SILENT */ { TELJJY_STATE_IDLE , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE }, 2618285612Sdelphij/* TIMEOUT */ { TELJJY_STATE_IDLE , TELJJY_STATE_IDLE , TELJJY_STATE_BYE , TELJJY_STATE_BYE , TELJJY_STATE_BYE } 2619285612Sdelphij} ; 2620285612Sdelphij 2621285612Sdelphijstatic short iTeljjyPostEvent [ ] [ 5 ] = 2622285612Sdelphij{ /*STATE_IDLE STATE_DAILOUT STATE_LOGIN STATE_CONNECT STATE_BYE */ 2623285612Sdelphij/* NULL */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2624285612Sdelphij/* START */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2625285612Sdelphij/* CONNECT */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2626285612Sdelphij/* DISCONNECT */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2627285612Sdelphij/* COMMAND */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2628285612Sdelphij/* LOGIN */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL }, 2629285612Sdelphij/* PROMPT */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_PROMPT , TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL }, 2630285612Sdelphij/* DATA */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2631285612Sdelphij/* ERROR */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_COMMAND, TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL }, 2632285612Sdelphij/* SILENT */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL , TELJJY_EVENT_NULL , TELJJY_EVENT_NULL }, 2633285612Sdelphij/* TIMEOUT */ { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_COMMAND, TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL } 2634285612Sdelphij} ; 2635285612Sdelphij 2636285612Sdelphijstatic short iTeljjySilentTimeout [ 5 ] = { 0, 0, 10, 5, 0 } ; 2637285612Sdelphijstatic short iTeljjyStateTimeout [ 5 ] = { 0, 120, 60, 60, 40 } ; 2638285612Sdelphij 2639285612Sdelphij#define TELJJY_STAY_CLOCK_STATE 0 2640285612Sdelphij#define TELJJY_CHANGE_CLOCK_STATE 1 2641285612Sdelphij 2642285612Sdelphij/* Command and replay */ 2643285612Sdelphij 2644285612Sdelphij#define TELJJY_REPLY_NONE 0 2645285612Sdelphij#define TELJJY_REPLY_4DATE 1 2646285612Sdelphij#define TELJJY_REPLY_TIME 2 2647285612Sdelphij#define TELJJY_REPLY_LEAPSEC 3 2648285612Sdelphij#define TELJJY_REPLY_LOOP 4 2649285612Sdelphij#define TELJJY_REPLY_PROMPT 5 2650285612Sdelphij#define TELJJY_REPLY_LOOPBACK 6 2651285612Sdelphij#define TELJJY_REPLY_COM 7 2652285612Sdelphij 2653285612Sdelphij#define TELJJY_COMMAND_START_SKIP_LOOPBACK 7 2654285612Sdelphij 2655285612Sdelphijstatic struct 2656285612Sdelphij{ 2657285612Sdelphij const char *command ; 2658285612Sdelphij int commandLength ; 2659285612Sdelphij int iEchobackReplyLength ; 2660285612Sdelphij int iExpectedReplyType ; 2661285612Sdelphij int iExpectedReplyLength ; 2662285612Sdelphij} teljjy_command_sequence[] = 2663285612Sdelphij{ 2664285612Sdelphij { NULL, 0, 0, 0, 0 }, /* Idle */ 2665285612Sdelphij { "LOOP\r" , 5, 4, TELJJY_REPLY_LOOP , 0 }, /* Getting into loopback mode */ 2666285612Sdelphij { ">" , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */ 2667285612Sdelphij { ">" , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */ 2668285612Sdelphij { ">" , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */ 2669285612Sdelphij { ">" , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */ 2670285612Sdelphij { ">" , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */ 2671285612Sdelphij { "COM\r" , 4, 3, TELJJY_REPLY_COM , 0 }, /* Exit from loopback mode */ 2672285612Sdelphij /* TELJJY_COMMAND_START_SKIP_LOOPBACK */ 2673285612Sdelphij { "TIME\r" , 5, 4, TELJJY_REPLY_TIME , 6 }, 2674285612Sdelphij { "4DATE\r" , 6, 5, TELJJY_REPLY_4DATE , 8 }, 2675285612Sdelphij { "LEAPSEC\r", 8, 7, TELJJY_REPLY_LEAPSEC , 2 }, 2676285612Sdelphij { "TIME\r" , 5, 4, TELJJY_REPLY_TIME , 6 }, 2677285612Sdelphij { "BYE\r" , 4, 3, TELJJY_REPLY_NONE , 0 }, 2678285612Sdelphij /* End of command */ 2679285612Sdelphij { NULL, 0, 0, 0, 0 } 2680285612Sdelphij} ; 2681285612Sdelphij 2682285612Sdelphij#define TELJJY_LOOPBACK_DELAY_THRESHOLD 700 /* Milli second */ 2683285612Sdelphij 2684285612Sdelphij#ifdef DEBUG 2685285612Sdelphij#define DEBUG_TELJJY_PRINTF(sFunc) { if ( debug ) { printf ( "refclock_jjy.c : %s : iClockState=%d iClockEvent=%d iTeljjySilentTimer=%d iTeljjyStateTimer=%d iClockCommandSeq=%d\n", sFunc, up->iClockState, up->iClockEvent, up->iTeljjySilentTimer, up->iTeljjyStateTimer, up->iClockCommandSeq ) ; } } 2686285612Sdelphij#else 2687285612Sdelphij#define DEBUG_TELJJY_PRINTF(sFunc) 2688285612Sdelphij#endif 2689285612Sdelphij 2690285612Sdelphij/**************************************************************************************************/ 2691285612Sdelphij 2692182007Srobertostatic int 2693285612Sdelphijjjy_start_telephone ( int unit, struct peer *peer, struct jjyunit *up ) 2694182007Sroberto{ 2695182007Sroberto 2696285612Sdelphij char sLog [ 80 ], sFirstThreeDigits [ 4 ] ; 2697316722Sdelphij int iNumberOfDigitsOfPhoneNumber, iCommaCount, iCommaPosition ; 2698316722Sdelphij size_t i ; 2699316722Sdelphij size_t iFirstThreeDigitsCount ; 2700182007Sroberto 2701285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Telephone JJY" ) ; 2702182007Sroberto 2703285612Sdelphij up->unittype = UNITTYPE_TELEPHONE ; 2704285612Sdelphij up->linespeed = SPEED232_TELEPHONE ; 2705285612Sdelphij up->linediscipline = LDISC_RAW ; 2706285612Sdelphij 2707285612Sdelphij up->pRawBreak = teljjy_raw_break ; 2708285612Sdelphij up->bWaitBreakString = TRUE ; 2709285612Sdelphij 2710285612Sdelphij up->bSkipCntrlCharOnly = TRUE ; 2711285612Sdelphij 2712285612Sdelphij up->iClockState = TELJJY_STATE_IDLE ; 2713285612Sdelphij up->iClockEvent = TELJJY_EVENT_NULL ; 2714285612Sdelphij 2715285612Sdelphij /* Check the telephone number */ 2716285612Sdelphij 2717285612Sdelphij if ( sys_phone[0] == NULL ) { 2718285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf must be specified." ) ; 2719285612Sdelphij up->bInitError = TRUE ; 2720285612Sdelphij return 1 ; 2721285612Sdelphij } 2722285612Sdelphij 2723285612Sdelphij if ( sys_phone[1] != NULL ) { 2724285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be only one." ) ; 2725285612Sdelphij up->bInitError = TRUE ; 2726285612Sdelphij return 1 ; 2727285612Sdelphij } 2728285612Sdelphij 2729285612Sdelphij iNumberOfDigitsOfPhoneNumber = iCommaCount = iCommaPosition = iFirstThreeDigitsCount = 0 ; 2730285612Sdelphij for ( i = 0 ; i < strlen( sys_phone[0] ) ; i ++ ) { 2731294569Sdelphij if ( isdigit( (u_char)sys_phone[0][i] ) ) { 2732285612Sdelphij if ( iFirstThreeDigitsCount < sizeof(sFirstThreeDigits)-1 ) { 2733294569Sdelphij sFirstThreeDigits[iFirstThreeDigitsCount++] = sys_phone[0][i] ; 2734285612Sdelphij } 2735285612Sdelphij iNumberOfDigitsOfPhoneNumber ++ ; 2736294569Sdelphij } else if ( sys_phone[0][i] == ',' ) { 2737285612Sdelphij iCommaCount ++ ; 2738285612Sdelphij if ( iCommaCount > 1 ) { 2739285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be zero or one comma." ) ; 2740285612Sdelphij up->bInitError = TRUE ; 2741285612Sdelphij return 1 ; 2742285612Sdelphij } 2743285612Sdelphij iFirstThreeDigitsCount = 0 ; 2744285612Sdelphij iCommaPosition = i ; 2745294569Sdelphij } else if ( sys_phone[0][i] != '-' ) { 2746285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be a number or a hyphen." ) ; 2747285612Sdelphij up->bInitError = TRUE ; 2748285612Sdelphij return 1 ; 2749285612Sdelphij } 2750285612Sdelphij } 2751285612Sdelphij sFirstThreeDigits[iFirstThreeDigitsCount] = 0 ; 2752285612Sdelphij 2753285612Sdelphij if ( iCommaCount == 1 ) { 2754285612Sdelphij if ( iCommaPosition != 1 || *sys_phone[0] != '0' ) { 2755285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : Getting an outside line should be '0,'." ) ; 2756285612Sdelphij up->bInitError = TRUE ; 2757285612Sdelphij return 1 ; 2758285612Sdelphij } 2759285612Sdelphij } 2760285612Sdelphij 2761285612Sdelphij if ( iNumberOfDigitsOfPhoneNumber - iCommaPosition < 6 || 10 < iNumberOfDigitsOfPhoneNumber - iCommaPosition ) { 2762285612Sdelphij /* Too short or too long */ 2763285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone=%s : Number of digits should be 6 to 10.", sys_phone[0] ) ; 2764285612Sdelphij up->bInitError = TRUE ; 2765285612Sdelphij return 1 ; 2766285612Sdelphij } 2767285612Sdelphij 2768285612Sdelphij if ( strncmp( sFirstThreeDigits + iCommaPosition, "00" , 2 ) == 0 2769285612Sdelphij || strncmp( sFirstThreeDigits + iCommaPosition, "10" , 2 ) == 0 2770285612Sdelphij || strncmp( sFirstThreeDigits + iCommaPosition, "11" , 2 ) == 0 2771285612Sdelphij || strncmp( sFirstThreeDigits + iCommaPosition, "12" , 2 ) == 0 2772285612Sdelphij || strncmp( sFirstThreeDigits + iCommaPosition, "171", 3 ) == 0 2773285612Sdelphij || strncmp( sFirstThreeDigits + iCommaPosition, "177", 3 ) == 0 2774285612Sdelphij || ( sFirstThreeDigits[0] == '0' && sFirstThreeDigits[2] == '0' ) ) { 2775285612Sdelphij /* Not allowed because of emergency numbers or special service numbers */ 2776285612Sdelphij msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone=%s : First 2 or 3 digits are not allowed.", sys_phone[0] ) ; 2777285612Sdelphij up->bInitError = TRUE ; 2778285612Sdelphij return 1 ; 2779285612Sdelphij } 2780285612Sdelphij 2781285612Sdelphij snprintf( sLog, sizeof(sLog), "phone=%s", sys_phone[0] ) ; 2782285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ; 2783285612Sdelphij 2784285612Sdelphij if ( peer->minpoll < 8 ) { 2785285612Sdelphij /* minpoll must be greater or equal to 8 ( 256 seconds = about 4 minutes ) */ 2786285612Sdelphij int oldminpoll = peer->minpoll ; 2787285612Sdelphij peer->minpoll = 8 ; 2788285612Sdelphij if ( peer->ppoll < peer->minpoll ) { 2789285612Sdelphij peer->ppoll = peer->minpoll ; 2790285612Sdelphij } 2791285612Sdelphij if ( peer->maxpoll < peer->minpoll ) { 2792285612Sdelphij peer->maxpoll = peer->minpoll ; 2793285612Sdelphij } 2794285612Sdelphij snprintf( sLog, sizeof(sLog), "minpoll=%d -> %d", oldminpoll, peer->minpoll ) ; 2795285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ; 2796285612Sdelphij } 2797285612Sdelphij 2798285612Sdelphij return 0 ; 2799285612Sdelphij 2800285612Sdelphij} 2801285612Sdelphij 2802285612Sdelphij/**************************************************************************************************/ 2803285612Sdelphij 2804285612Sdelphijstatic int 2805285612Sdelphijjjy_receive_telephone ( struct recvbuf *rbufp ) 2806285612Sdelphij{ 2807285612Sdelphij#ifdef DEBUG 2808285612Sdelphij static const char *sFunctionName = "jjy_receive_telephone" ; 2809285612Sdelphij#endif 2810285612Sdelphij 2811285612Sdelphij struct peer *peer; 2812285612Sdelphij struct refclockproc *pp ; 2813285612Sdelphij struct jjyunit *up ; 2814182007Sroberto char *pBuf ; 2815285612Sdelphij int iLen ; 2816285612Sdelphij short iPreviousModemState ; 2817182007Sroberto 2818285612Sdelphij peer = rbufp->recv_peer ; 2819182007Sroberto pp = peer->procptr ; 2820285612Sdelphij up = pp->unitptr ; 2821182007Sroberto 2822285612Sdelphij DEBUG_TELJJY_PRINTF( sFunctionName ) ; 2823285612Sdelphij 2824285612Sdelphij if ( up->iClockState == TELJJY_STATE_IDLE 2825285612Sdelphij || up->iClockState == TELJJY_STATE_DAILOUT 2826285612Sdelphij || up->iClockState == TELJJY_STATE_BYE ) { 2827285612Sdelphij 2828285612Sdelphij iPreviousModemState = getModemState( up ) ; 2829285612Sdelphij 2830285612Sdelphij modem_receive ( rbufp ) ; 2831285612Sdelphij 2832285612Sdelphij if ( iPreviousModemState != up->iModemState ) { 2833285612Sdelphij /* Modem state is changed just now. */ 2834285612Sdelphij if ( isModemStateDisconnect( up->iModemState ) ) { 2835285612Sdelphij up->iClockEvent = TELJJY_EVENT_DISCONNECT ; 2836285612Sdelphij teljjy_control ( peer, pp, up ) ; 2837285612Sdelphij } else if ( isModemStateConnect( up->iModemState ) ) { 2838285612Sdelphij up->iClockEvent = TELJJY_EVENT_CONNECT ; 2839285612Sdelphij teljjy_control ( peer, pp, up ) ; 2840285612Sdelphij } 2841285612Sdelphij } 2842285612Sdelphij 2843285612Sdelphij return JJY_RECEIVE_WAIT ; 2844285612Sdelphij 2845285612Sdelphij } 2846285612Sdelphij 2847182007Sroberto if ( up->linediscipline == LDISC_RAW ) { 2848285612Sdelphij pBuf = up->sTextBuf ; 2849285612Sdelphij iLen = up->iTextBufLen ; 2850182007Sroberto } else { 2851285612Sdelphij pBuf = pp->a_lastcode ; 2852285612Sdelphij iLen = pp->lencode ; 2853182007Sroberto } 2854182007Sroberto 2855285612Sdelphij up->iTeljjySilentTimer = 0 ; 2856285612Sdelphij if ( iLen == 7 && strncmp( pBuf, "Name ? ", 7 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_LOGIN ; } 2857285612Sdelphij else if ( iLen == 1 && strncmp( pBuf, ">" , 1 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_PROMPT ; } 2858285612Sdelphij else if ( iLen >= 1 && strncmp( pBuf, "?" , 1 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_ERROR ; } 2859285612Sdelphij else { up->iClockEvent = TELJJY_EVENT_DATA ; } 2860182007Sroberto 2861285612Sdelphij teljjy_control ( peer, pp, up ) ; 2862182007Sroberto 2863285612Sdelphij return JJY_RECEIVE_WAIT ; 2864285612Sdelphij 2865285612Sdelphij} 2866285612Sdelphij 2867285612Sdelphij/**************************************************************************************************/ 2868285612Sdelphij 2869285612Sdelphijstatic void 2870285612Sdelphijjjy_poll_telephone ( int unit, struct peer *peer ) 2871285612Sdelphij{ 2872182007Sroberto#ifdef DEBUG 2873285612Sdelphij static const char *sFunctionName = "jjy_poll_telephone" ; 2874182007Sroberto#endif 2875285612Sdelphij 2876285612Sdelphij struct refclockproc *pp ; 2877285612Sdelphij struct jjyunit *up ; 2878285612Sdelphij 2879285612Sdelphij pp = peer->procptr ; 2880285612Sdelphij up = pp->unitptr ; 2881285612Sdelphij 2882285612Sdelphij DEBUG_TELJJY_PRINTF( sFunctionName ) ; 2883285612Sdelphij 2884285612Sdelphij if ( up->iClockState == TELJJY_STATE_IDLE ) { 2885285612Sdelphij up->iRawBufLen = 0 ; 2886285612Sdelphij up->iLineBufLen = 0 ; 2887285612Sdelphij up->iTextBufLen = 0 ; 2888285612Sdelphij } 2889285612Sdelphij 2890285612Sdelphij up->iClockEvent = TELJJY_EVENT_START ; 2891285612Sdelphij teljjy_control ( peer, pp, up ) ; 2892285612Sdelphij 2893285612Sdelphij} 2894285612Sdelphij 2895285612Sdelphij/**************************************************************************************************/ 2896285612Sdelphij 2897285612Sdelphijstatic void 2898285612Sdelphijjjy_timer_telephone ( int unit, struct peer *peer ) 2899285612Sdelphij{ 2900182007Sroberto#ifdef DEBUG 2901285612Sdelphij static const char *sFunctionName = "jjy_timer_telephone" ; 2902182007Sroberto#endif 2903285612Sdelphij 2904285612Sdelphij struct refclockproc *pp ; 2905285612Sdelphij struct jjyunit *up ; 2906285612Sdelphij short iPreviousModemState ; 2907285612Sdelphij 2908285612Sdelphij pp = peer->procptr ; 2909285612Sdelphij up = pp->unitptr ; 2910285612Sdelphij 2911285612Sdelphij DEBUG_TELJJY_PRINTF( sFunctionName ) ; 2912285612Sdelphij 2913285612Sdelphij if ( iTeljjySilentTimeout[up->iClockState] != 0 ) { 2914285612Sdelphij up->iTeljjySilentTimer++ ; 2915285612Sdelphij if ( iTeljjySilentTimeout[up->iClockState] <= up->iTeljjySilentTimer ) { 2916285612Sdelphij up->iClockEvent = TELJJY_EVENT_SILENT ; 2917285612Sdelphij teljjy_control ( peer, pp, up ) ; 2918285612Sdelphij } 2919285612Sdelphij } 2920285612Sdelphij 2921285612Sdelphij if ( iTeljjyStateTimeout[up->iClockState] != 0 ) { 2922285612Sdelphij up->iTeljjyStateTimer++ ; 2923285612Sdelphij if ( iTeljjyStateTimeout[up->iClockState] <= up->iTeljjyStateTimer ) { 2924285612Sdelphij up->iClockEvent = TELJJY_EVENT_TIMEOUT ; 2925285612Sdelphij teljjy_control ( peer, pp, up ) ; 2926285612Sdelphij } 2927285612Sdelphij } 2928285612Sdelphij 2929285612Sdelphij if ( isModemStateTimerOn( up ) ) { 2930285612Sdelphij 2931285612Sdelphij iPreviousModemState = getModemState( up ) ; 2932285612Sdelphij 2933285612Sdelphij modem_timer ( unit, peer ) ; 2934285612Sdelphij 2935285612Sdelphij if ( iPreviousModemState != up->iModemState ) { 2936285612Sdelphij /* Modem state is changed just now. */ 2937285612Sdelphij if ( isModemStateDisconnect( up->iModemState ) ) { 2938285612Sdelphij up->iClockEvent = TELJJY_EVENT_DISCONNECT ; 2939285612Sdelphij teljjy_control ( peer, pp, up ) ; 2940285612Sdelphij } else if ( isModemStateConnect( up->iModemState ) ) { 2941285612Sdelphij up->iClockEvent = TELJJY_EVENT_CONNECT ; 2942285612Sdelphij teljjy_control ( peer, pp, up ) ; 2943182007Sroberto } 2944182007Sroberto } 2945182007Sroberto 2946285612Sdelphij } 2947182007Sroberto 2948285612Sdelphij} 2949285612Sdelphij 2950285612Sdelphij/**************************************************************************************************/ 2951285612Sdelphij 2952285612Sdelphijstatic void 2953285612Sdelphijteljjy_control ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 2954285612Sdelphij{ 2955285612Sdelphij 2956285612Sdelphij int i, rc ; 2957285612Sdelphij short iPostEvent = TELJJY_EVENT_NULL ; 2958285612Sdelphij 2959285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_control" ) ; 2960285612Sdelphij 2961285612Sdelphij rc = (*pTeljjyHandler[up->iClockEvent][up->iClockState])( peer, pp, up ) ; 2962285612Sdelphij 2963285612Sdelphij if ( rc == TELJJY_CHANGE_CLOCK_STATE ) { 2964285612Sdelphij iPostEvent = iTeljjyPostEvent[up->iClockEvent][up->iClockState] ; 2965182007Sroberto#ifdef DEBUG 2966285612Sdelphij if ( debug ) { 2967285612Sdelphij printf( "refclock_jjy.c : teljjy_control : iClockState=%hd -> %hd iPostEvent=%hd\n", 2968285612Sdelphij up->iClockState, iTeljjyNextState[up->iClockEvent][up->iClockState], iPostEvent ) ; 2969285612Sdelphij } 2970182007Sroberto#endif 2971285612Sdelphij up->iTeljjySilentTimer = 0 ; 2972285612Sdelphij if ( up->iClockState != iTeljjyNextState[up->iClockEvent][up->iClockState] ) { 2973285612Sdelphij /* Telephone JJY state is changing now */ 2974285612Sdelphij up->iTeljjyStateTimer = 0 ; 2975285612Sdelphij up->bLineError = FALSE ; 2976285612Sdelphij up->iClockCommandSeq = 0 ; 2977285612Sdelphij up->iTimestampCount = 0 ; 2978285612Sdelphij up->iLoopbackCount = 0 ; 2979285612Sdelphij for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) { 2980285612Sdelphij up->bLoopbackTimeout[i] = FALSE ; 2981182007Sroberto } 2982285612Sdelphij if (iTeljjyNextState[up->iClockEvent][up->iClockState] == TELJJY_STATE_IDLE ) { 2983285612Sdelphij /* Telephone JJY state is changing to IDLE just now */ 2984285612Sdelphij up->iProcessState = JJY_PROCESS_STATE_DONE ; 2985285612Sdelphij } 2986285612Sdelphij } 2987285612Sdelphij up->iClockState = iTeljjyNextState[up->iClockEvent][up->iClockState] ; 2988182007Sroberto 2989285612Sdelphij } 2990182007Sroberto 2991285612Sdelphij if ( iPostEvent != TELJJY_EVENT_NULL ) { 2992285612Sdelphij up->iClockEvent = iPostEvent ; 2993285612Sdelphij teljjy_control ( peer, pp, up ) ; 2994285612Sdelphij } 2995285612Sdelphij 2996285612Sdelphij up->iClockEvent = TELJJY_EVENT_NULL ; 2997285612Sdelphij 2998285612Sdelphij} 2999285612Sdelphij 3000285612Sdelphij/**************************************************************************************************/ 3001285612Sdelphij 3002285612Sdelphijstatic void 3003285612Sdelphijteljjy_setDelay ( struct peer *peer, struct jjyunit *up ) 3004285612Sdelphij{ 3005285612Sdelphij 3006285612Sdelphij char sLog [ 60 ] ; 3007285612Sdelphij int milliSecond, microSecond ; 3008285612Sdelphij 3009285612Sdelphij gettimeofday( &(up->delayTime[up->iLoopbackCount]), NULL ) ; 3010285612Sdelphij 3011285612Sdelphij up->delayTime[up->iLoopbackCount].tv_sec -= up->sendTime[up->iLoopbackCount].tv_sec ; 3012285612Sdelphij up->delayTime[up->iLoopbackCount].tv_usec -= up->sendTime[up->iLoopbackCount].tv_usec ; 3013285612Sdelphij if ( up->delayTime[up->iLoopbackCount].tv_usec < 0 ) { 3014285612Sdelphij up->delayTime[up->iLoopbackCount].tv_sec -- ; 3015285612Sdelphij up->delayTime[up->iLoopbackCount].tv_usec += 1000000 ; 3016285612Sdelphij } 3017285612Sdelphij 3018285612Sdelphij milliSecond = up->delayTime[up->iLoopbackCount].tv_usec / 1000 ; 3019285612Sdelphij microSecond = up->delayTime[up->iLoopbackCount].tv_usec - milliSecond * 1000 ; 3020285612Sdelphij milliSecond += up->delayTime[up->iLoopbackCount].tv_sec * 1000 ; 3021285612Sdelphij 3022285612Sdelphij snprintf( sLog, sizeof(sLog), JJY_CLOCKSTATS_MESSAGE_LOOPBACK_DELAY, 3023285612Sdelphij milliSecond, microSecond ) ; 3024285612Sdelphij 3025285612Sdelphij if ( milliSecond > TELJJY_LOOPBACK_DELAY_THRESHOLD ) { 3026285612Sdelphij /* Delay > 700 mS */ 3027285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ; 3028285612Sdelphij } else { 3029285612Sdelphij /* Delay <= 700 mS */ 3030285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ; 3031285612Sdelphij } 3032285612Sdelphij 3033285612Sdelphij} 3034285612Sdelphij 3035285612Sdelphij/**************************************************************************************************/ 3036285612Sdelphij 3037285612Sdelphijstatic int 3038285612Sdelphijteljjy_getDelay ( struct peer *peer, struct jjyunit *up ) 3039285612Sdelphij{ 3040285612Sdelphij 3041285612Sdelphij struct timeval maxTime, minTime, averTime ; 3042285612Sdelphij int i ; 3043285612Sdelphij int minIndex = 0, maxIndex = 0, iAverCount = 0 ; 3044285612Sdelphij int iThresholdSecond, iThresholdMicroSecond ; 3045285612Sdelphij int iPercent ; 3046285612Sdelphij 3047285612Sdelphij minTime.tv_sec = minTime.tv_usec = 0 ; 3048285612Sdelphij maxTime.tv_sec = maxTime.tv_usec = 0 ; 3049285612Sdelphij 3050285612Sdelphij iThresholdSecond = TELJJY_LOOPBACK_DELAY_THRESHOLD / 1000 ; 3051285612Sdelphij iThresholdMicroSecond = ( TELJJY_LOOPBACK_DELAY_THRESHOLD - ( TELJJY_LOOPBACK_DELAY_THRESHOLD / 1000 ) * 1000 ) * 1000 ; 3052285612Sdelphij 3053285612Sdelphij up->iLoopbackValidCount = 0 ; 3054285612Sdelphij 3055285612Sdelphij for ( i = 0 ; i < MAX_LOOPBACK && i < up->iLoopbackCount ; i ++ ) { 3056285612Sdelphij if ( up->bLoopbackTimeout[i] 3057285612Sdelphij || up->delayTime[i].tv_sec > iThresholdSecond 3058285612Sdelphij || ( up->delayTime[i].tv_sec == iThresholdSecond 3059285612Sdelphij && up->delayTime[i].tv_usec > iThresholdMicroSecond ) ) { 3060285612Sdelphij continue ; 3061285612Sdelphij } 3062285612Sdelphij if ( up->iLoopbackValidCount == 0 ) { 3063285612Sdelphij minTime.tv_sec = up->delayTime[i].tv_sec ; 3064285612Sdelphij minTime.tv_usec = up->delayTime[i].tv_usec ; 3065285612Sdelphij maxTime.tv_sec = up->delayTime[i].tv_sec ; 3066285612Sdelphij maxTime.tv_usec = up->delayTime[i].tv_usec ; 3067285612Sdelphij minIndex = maxIndex = i ; 3068285612Sdelphij } else if ( minTime.tv_sec > up->delayTime[i].tv_sec 3069285612Sdelphij || ( minTime.tv_sec == up->delayTime[i].tv_sec 3070285612Sdelphij && minTime.tv_usec > up->delayTime[i].tv_usec ) ) { 3071285612Sdelphij minTime.tv_sec = up->delayTime[i].tv_sec ; 3072285612Sdelphij minTime.tv_usec = up->delayTime[i].tv_usec ; 3073285612Sdelphij minIndex = i ; 3074285612Sdelphij } else if ( maxTime.tv_sec < up->delayTime[i].tv_sec 3075285612Sdelphij || ( maxTime.tv_sec == up->delayTime[i].tv_sec 3076285612Sdelphij && maxTime.tv_usec < up->delayTime[i].tv_usec ) ) { 3077285612Sdelphij maxTime.tv_sec = up->delayTime[i].tv_sec ; 3078285612Sdelphij maxTime.tv_usec = up->delayTime[i].tv_usec ; 3079285612Sdelphij maxIndex = i ; 3080285612Sdelphij } 3081285612Sdelphij up->iLoopbackValidCount ++ ; 3082285612Sdelphij } 3083285612Sdelphij 3084285612Sdelphij if ( up->iLoopbackValidCount < 2 ) { 3085285612Sdelphij return -1 ; 3086285612Sdelphij } 3087285612Sdelphij 3088285612Sdelphij averTime.tv_usec = 0; 3089285612Sdelphij 3090285612Sdelphij for ( i = 0 ; i < MAX_LOOPBACK && i < up->iLoopbackCount ; i ++ ) { 3091285612Sdelphij if ( up->bLoopbackTimeout[i] 3092285612Sdelphij || up->delayTime[i].tv_sec > iThresholdSecond 3093285612Sdelphij || ( up->delayTime[i].tv_sec == iThresholdSecond 3094285612Sdelphij && up->delayTime[i].tv_usec > iThresholdMicroSecond ) ) { 3095285612Sdelphij continue ; 3096285612Sdelphij } 3097285612Sdelphij if ( up->iLoopbackValidCount >= 3 && i == maxIndex ) { 3098285612Sdelphij continue ; 3099285612Sdelphij } 3100285612Sdelphij if ( up->iLoopbackValidCount >= 4 && i == minIndex ) { 3101285612Sdelphij continue ; 3102285612Sdelphij } 3103285612Sdelphij averTime.tv_usec += up->delayTime[i].tv_usec ; 3104285612Sdelphij iAverCount ++ ; 3105285612Sdelphij } 3106285612Sdelphij 3107285612Sdelphij if ( iAverCount == 0 ) { 3108285612Sdelphij /* This is never happened. */ 3109285612Sdelphij /* Previous for-if-for blocks assure iAverCount > 0. */ 3110285612Sdelphij /* This code avoids a claim by the coverity scan tool. */ 3111285612Sdelphij return -1 ; 3112285612Sdelphij } 3113285612Sdelphij 3114285612Sdelphij /* mode 101 = 1%, mode 150 = 50%, mode 180 = 80% */ 3115285612Sdelphij 3116285612Sdelphij iPercent = ( peer->ttl - 100 ) ; 3117285612Sdelphij 3118285612Sdelphij /* Average delay time in milli second */ 3119285612Sdelphij 3120285612Sdelphij return ( ( averTime.tv_usec / iAverCount ) * iPercent ) / 100000 ; 3121285612Sdelphij 3122285612Sdelphij} 3123285612Sdelphij 3124285612Sdelphij/******************************/ 3125285612Sdelphijstatic int 3126285612Sdelphijteljjy_idle_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3127285612Sdelphij{ 3128285612Sdelphij 3129285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_idle_ignore" ) ; 3130285612Sdelphij 3131285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3132285612Sdelphij 3133285612Sdelphij} 3134285612Sdelphij 3135285612Sdelphij/******************************/ 3136285612Sdelphijstatic int 3137285612Sdelphijteljjy_idle_dialout ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3138285612Sdelphij{ 3139285612Sdelphij 3140285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_idle_dialout" ) ; 3141285612Sdelphij 3142285612Sdelphij modem_connect ( peer->refclkunit, peer ) ; 3143285612Sdelphij 3144285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3145285612Sdelphij 3146285612Sdelphij} 3147285612Sdelphij 3148285612Sdelphij/******************************/ 3149285612Sdelphijstatic int 3150285612Sdelphijteljjy_dial_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3151285612Sdelphij{ 3152285612Sdelphij 3153285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_dial_ignore" ) ; 3154285612Sdelphij 3155285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3156285612Sdelphij 3157285612Sdelphij} 3158285612Sdelphij 3159285612Sdelphij/******************************/ 3160285612Sdelphijstatic int 3161285612Sdelphijteljjy_dial_login ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3162285612Sdelphij{ 3163285612Sdelphij 3164285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_dial_login" ) ; 3165285612Sdelphij 3166285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3167285612Sdelphij 3168285612Sdelphij} 3169285612Sdelphij 3170285612Sdelphij/******************************/ 3171285612Sdelphijstatic int 3172285612Sdelphijteljjy_dial_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3173285612Sdelphij{ 3174285612Sdelphij 3175285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_dial_disc" ) ; 3176285612Sdelphij 3177285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3178285612Sdelphij 3179285612Sdelphij} 3180285612Sdelphij 3181285612Sdelphij/******************************/ 3182285612Sdelphijstatic int 3183285612Sdelphijteljjy_login_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3184285612Sdelphij{ 3185285612Sdelphij 3186285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_login_ignore" ) ; 3187285612Sdelphij 3188285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3189285612Sdelphij 3190285612Sdelphij} 3191285612Sdelphij 3192285612Sdelphij/******************************/ 3193285612Sdelphijstatic int 3194285612Sdelphijteljjy_login_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3195285612Sdelphij{ 3196285612Sdelphij 3197285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_login_disc" ) ; 3198285612Sdelphij 3199285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3200285612Sdelphij 3201285612Sdelphij} 3202285612Sdelphij 3203285612Sdelphij/******************************/ 3204285612Sdelphijstatic int 3205285612Sdelphijteljjy_login_conn ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3206285612Sdelphij{ 3207285612Sdelphij 3208285612Sdelphij int i ; 3209285612Sdelphij 3210285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_login_conn" ) ; 3211285612Sdelphij 3212285612Sdelphij up->bLineError = FALSE ; 3213285612Sdelphij up->iClockCommandSeq = 0 ; 3214285612Sdelphij up->iTimestampCount = 0 ; 3215285612Sdelphij up->iLoopbackCount = 0 ; 3216285612Sdelphij for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) { 3217285612Sdelphij up->bLoopbackTimeout[i] = FALSE ; 3218285612Sdelphij } 3219285612Sdelphij 3220285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3221285612Sdelphij 3222285612Sdelphij} 3223285612Sdelphij 3224285612Sdelphij/******************************/ 3225285612Sdelphijstatic int 3226285612Sdelphijteljjy_login_login ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3227285612Sdelphij{ 3228285612Sdelphij 3229294569Sdelphij const char * pCmd ; 3230294569Sdelphij int iCmdLen ; 3231285612Sdelphij 3232285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_login_login" ) ; 3233285612Sdelphij 3234285612Sdelphij /* Send a guest user ID */ 3235285612Sdelphij pCmd = "TJJY\r" ; 3236285612Sdelphij 3237285612Sdelphij /* Send login ID */ 3238285612Sdelphij iCmdLen = strlen( pCmd ) ; 3239285612Sdelphij if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 3240285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 3241285612Sdelphij } 3242285612Sdelphij 3243285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 3244285612Sdelphij 3245285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3246285612Sdelphij 3247285612Sdelphij} 3248285612Sdelphij 3249285612Sdelphij/******************************/ 3250285612Sdelphijstatic int 3251285612Sdelphijteljjy_login_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3252285612Sdelphij{ 3253285612Sdelphij 3254285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_login_silent" ) ; 3255285612Sdelphij 3256285612Sdelphij if ( write( pp->io.fd, "\r", 1 ) != 1 ) { 3257285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 3258285612Sdelphij } 3259285612Sdelphij 3260285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, "\r" ) ; 3261285612Sdelphij 3262285612Sdelphij up->iTeljjySilentTimer = 0 ; 3263285612Sdelphij 3264285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3265285612Sdelphij 3266285612Sdelphij} 3267285612Sdelphij 3268285612Sdelphij/******************************/ 3269285612Sdelphijstatic int 3270285612Sdelphijteljjy_login_error ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3271285612Sdelphij{ 3272285612Sdelphij 3273285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_login_error" ) ; 3274285612Sdelphij 3275285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3276285612Sdelphij 3277285612Sdelphij} 3278285612Sdelphij 3279285612Sdelphij/******************************/ 3280285612Sdelphijstatic int 3281285612Sdelphijteljjy_conn_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3282285612Sdelphij{ 3283285612Sdelphij 3284285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_conn_ignore" ) ; 3285285612Sdelphij 3286285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3287285612Sdelphij 3288285612Sdelphij} 3289285612Sdelphij 3290285612Sdelphij/******************************/ 3291285612Sdelphijstatic int 3292285612Sdelphijteljjy_conn_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3293285612Sdelphij{ 3294285612Sdelphij 3295285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_conn_disc" ) ; 3296285612Sdelphij 3297285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3298285612Sdelphij 3299285612Sdelphij} 3300285612Sdelphij 3301285612Sdelphij/******************************/ 3302285612Sdelphijstatic int 3303285612Sdelphijteljjy_conn_send ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3304285612Sdelphij{ 3305285612Sdelphij 3306294569Sdelphij const char * pCmd ; 3307294569Sdelphij int i, iLen, iNextClockState ; 3308330567Sgordon char sLog [ 120 ] ; 3309285612Sdelphij 3310285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_conn_send" ) ; 3311285612Sdelphij 3312285612Sdelphij if ( up->iClockCommandSeq > 0 3313285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].command == NULL ) { 3314285612Sdelphij /* Command sequence has been completed */ 3315285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3316285612Sdelphij } 3317285612Sdelphij 3318285612Sdelphij if ( up->iClockCommandSeq == 0 && peer->ttl == 100 ) { 3319285612Sdelphij /* Skip loopback */ 3320285612Sdelphij 3321285612Sdelphij up->iClockCommandSeq = TELJJY_COMMAND_START_SKIP_LOOPBACK ; 3322285612Sdelphij 3323285612Sdelphij } else if ( up->iClockCommandSeq == 0 && peer->ttl != 100 ) { 3324285612Sdelphij /* Loopback start */ 3325285612Sdelphij 3326285612Sdelphij up->iLoopbackCount = 0 ; 3327285612Sdelphij for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) { 3328285612Sdelphij up->bLoopbackTimeout[i] = FALSE ; 3329285612Sdelphij } 3330285612Sdelphij 3331285612Sdelphij } else if ( up->iClockCommandSeq > 0 && peer->ttl != 100 3332285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK 3333285612Sdelphij && up->iLoopbackCount < MAX_LOOPBACK ) { 3334285612Sdelphij /* Loopback character comes */ 3335182007Sroberto#ifdef DEBUG 3336285612Sdelphij if ( debug ) { 3337330567Sgordon printf( "refclock_jjy.c : teljjy_conn_send : iClockCommandSeq=%d iLoopbackCount=%d\n", 3338330567Sgordon up->iClockCommandSeq, up->iLoopbackCount ) ; 3339285612Sdelphij } 3340182007Sroberto#endif 3341285612Sdelphij 3342285612Sdelphij teljjy_setDelay( peer, up ) ; 3343285612Sdelphij 3344285612Sdelphij up->iLoopbackCount ++ ; 3345285612Sdelphij 3346285612Sdelphij } 3347285612Sdelphij 3348285612Sdelphij up->iClockCommandSeq++ ; 3349285612Sdelphij 3350285612Sdelphij pCmd = teljjy_command_sequence[up->iClockCommandSeq].command ; 3351285612Sdelphij iLen = teljjy_command_sequence[up->iClockCommandSeq].commandLength ; 3352285612Sdelphij 3353285612Sdelphij if ( pCmd != NULL ) { 3354285612Sdelphij 3355285612Sdelphij if ( write( pp->io.fd, pCmd, iLen ) != iLen ) { 3356285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 3357182007Sroberto } 3358182007Sroberto 3359285612Sdelphij if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) { 3360285612Sdelphij /* Loopback character and timestamp */ 3361330567Sgordon if ( up->iLoopbackCount < MAX_LOOPBACK ) { 3362330567Sgordon gettimeofday( &(up->sendTime[up->iLoopbackCount]), NULL ) ; 3363330567Sgordon up->bLoopbackMode = TRUE ; 3364330567Sgordon } else { 3365330567Sgordon /* This else-block is never come. */ 3366330567Sgordon /* This code avoid wrong report of the coverity static analysis scan tool. */ 3367330567Sgordon snprintf( sLog, sizeof(sLog)-1, "refclock_jjy.c ; teljjy_conn_send ; iClockCommandSeq=%d iLoopbackCount=%d MAX_LOOPBACK=%d", 3368330567Sgordon up->iClockCommandSeq, up->iLoopbackCount, MAX_LOOPBACK ) ; 3369330567Sgordon jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_BUG, sLog ) ; 3370330567Sgordon msyslog ( LOG_ERR, "%s", sLog ) ; 3371330567Sgordon up->bLoopbackMode = FALSE ; 3372330567Sgordon } 3373285612Sdelphij } else { 3374285612Sdelphij /* Regular command */ 3375285612Sdelphij up->bLoopbackMode = FALSE ; 3376285612Sdelphij } 3377182007Sroberto 3378285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 3379182007Sroberto 3380285612Sdelphij if ( teljjy_command_sequence[up->iClockCommandSeq+1].command == NULL ) { 3381285612Sdelphij /* Last command of the command sequence */ 3382285612Sdelphij iNextClockState = TELJJY_CHANGE_CLOCK_STATE ; 3383285612Sdelphij } else { 3384285612Sdelphij /* More commands to be issued */ 3385285612Sdelphij iNextClockState = TELJJY_STAY_CLOCK_STATE ; 3386285612Sdelphij } 3387285612Sdelphij 3388285612Sdelphij } else { 3389285612Sdelphij 3390285612Sdelphij iNextClockState = TELJJY_CHANGE_CLOCK_STATE ; 3391285612Sdelphij 3392285612Sdelphij } 3393285612Sdelphij 3394285612Sdelphij return iNextClockState ; 3395285612Sdelphij 3396285612Sdelphij} 3397285612Sdelphij 3398285612Sdelphij/******************************/ 3399285612Sdelphijstatic int 3400285612Sdelphijteljjy_conn_data ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3401285612Sdelphij{ 3402285612Sdelphij 3403285612Sdelphij char *pBuf ; 3404285612Sdelphij int iLen, rc ; 3405285612Sdelphij char sLog [ 80 ] ; 3406285612Sdelphij char bAdjustment ; 3407285612Sdelphij 3408285612Sdelphij 3409285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_conn_data" ) ; 3410285612Sdelphij 3411285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 3412285612Sdelphij pBuf = up->sTextBuf ; 3413285612Sdelphij iLen = up->iTextBufLen ; 3414285612Sdelphij } else { 3415285612Sdelphij pBuf = pp->a_lastcode ; 3416285612Sdelphij iLen = pp->lencode ; 3417285612Sdelphij } 3418285612Sdelphij 3419285612Sdelphij if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength == iLen 3420285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK 3421285612Sdelphij && up->sTextBuf[0] == *(teljjy_command_sequence[up->iClockCommandSeq].command) 3422285612Sdelphij && up->iLoopbackCount < MAX_LOOPBACK ) { 3423285612Sdelphij /* Loopback */ 3424285612Sdelphij 3425285612Sdelphij teljjy_setDelay( peer, up ) ; 3426285612Sdelphij 3427285612Sdelphij up->iLoopbackCount ++ ; 3428285612Sdelphij 3429285612Sdelphij } else if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength == iLen 3430285612Sdelphij && strncmp( pBuf, teljjy_command_sequence[up->iClockCommandSeq].command, iLen ) == 0 ) { 3431285612Sdelphij /* Maybe echoback */ 3432285612Sdelphij 3433285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, JJY_CLOCKSTATS_MESSAGE_ECHOBACK ) ; 3434285612Sdelphij 3435285612Sdelphij } else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen 3436285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_4DATE ) { 3437285612Sdelphij /* 4DATE<CR> -> YYYYMMDD<CR> */ 3438285612Sdelphij 3439285612Sdelphij rc = sscanf ( pBuf, "%4d%2d%2d", &up->year, &up->month, &up->day ) ; 3440285612Sdelphij 3441285612Sdelphij if ( rc != 3 || up->year < 2000 || 2099 <= up->year 3442285612Sdelphij || up->month < 1 || 12 < up->month || up->day < 1 || 31 < up->day ) { 3443285612Sdelphij /* Invalid date */ 3444285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE, 3445285612Sdelphij rc, up->year, up->month, up->day ) ; 3446285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 3447285612Sdelphij up->bLineError = TRUE ; 3448285612Sdelphij } 3449285612Sdelphij 3450285612Sdelphij } else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen 3451285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LEAPSEC 3452285612Sdelphij && ( strncmp( pBuf, " 0", 2 ) == 0 || strncmp( pBuf, "+1", 2 ) == 0 || strncmp( pBuf, "-1", 2 ) == 0 ) ) { 3453285612Sdelphij /* LEAPSEC<CR> -> XX<CR> ( One of <SP>0, +1, -1 ) */ 3454285612Sdelphij 3455285612Sdelphij rc = sscanf ( pBuf, "%2d", &up->leapsecond ) ; 3456285612Sdelphij 3457285612Sdelphij if ( rc != 1 || up->leapsecond < -1 || 1 < up->leapsecond ) { 3458285612Sdelphij /* Invalid leap second */ 3459285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_LEAP, 3460285612Sdelphij pBuf ) ; 3461285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 3462285612Sdelphij up->bLineError = TRUE ; 3463285612Sdelphij } 3464285612Sdelphij 3465285612Sdelphij } else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen 3466285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_TIME ) { 3467285612Sdelphij /* TIME<CR> -> HHMMSS<CR> ( 3 times on second ) */ 3468285612Sdelphij 3469285612Sdelphij rc = sscanf ( pBuf, "%2d%2d%2d", &up->hour, &up->minute, &up->second ) ; 3470285612Sdelphij 3471285612Sdelphij if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) { 3472285612Sdelphij /* Invalid time */ 3473285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME, 3474285612Sdelphij rc, up->hour, up->minute, up->second ) ; 3475285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 3476285612Sdelphij up->bLineError = TRUE ; 3477285612Sdelphij } 3478285612Sdelphij up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ; 3479285612Sdelphij 3480285612Sdelphij up->iTimestampCount++ ; 3481285612Sdelphij 3482285612Sdelphij if ( up->iTimestampCount == 6 && ! up->bLineError ) { 3483285612Sdelphij#if DEBUG 3484285612Sdelphij printf( "refclock_jjy.c : teljjy_conn_data : bLineError=%d iTimestamp=%d, %d, %d\n", 3485285612Sdelphij up->bLineError, 3486285612Sdelphij up->iTimestamp[3], up->iTimestamp[4], up->iTimestamp[5] ) ; 3487285612Sdelphij#endif 3488285612Sdelphij bAdjustment = TRUE ; 3489285612Sdelphij 3490285612Sdelphij if ( peer->ttl == 100 ) { 3491285612Sdelphij /* mode=100 */ 3492285612Sdelphij up->msecond = 0 ; 3493285612Sdelphij } else { 3494285612Sdelphij /* mode=101 to 110 */ 3495285612Sdelphij up->msecond = teljjy_getDelay( peer, up ) ; 3496285612Sdelphij if (up->msecond < 0 ) { 3497285612Sdelphij up->msecond = 0 ; 3498285612Sdelphij bAdjustment = FALSE ; 3499182007Sroberto } 3500182007Sroberto } 3501182007Sroberto 3502285612Sdelphij if ( ( up->iTimestamp[3] - 15 ) <= up->iTimestamp[2] 3503285612Sdelphij && up->iTimestamp[2] <= up->iTimestamp[3] 3504285612Sdelphij && ( up->iTimestamp[3] + 1 ) == up->iTimestamp[4] 3505285612Sdelphij && ( up->iTimestamp[4] + 1 ) == up->iTimestamp[5] ) { 3506285612Sdelphij /* Non over midnight */ 3507285612Sdelphij 3508285612Sdelphij jjy_synctime( peer, pp, up ) ; 3509285612Sdelphij 3510285612Sdelphij if ( peer->ttl != 100 ) { 3511285612Sdelphij if ( bAdjustment ) { 3512285612Sdelphij snprintf( sLog, sizeof(sLog), 3513285612Sdelphij JJY_CLOCKSTATS_MESSAGE_DELAY_ADJUST, 3514285612Sdelphij up->msecond, up->iLoopbackValidCount, MAX_LOOPBACK ) ; 3515285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ; 3516285612Sdelphij } else { 3517285612Sdelphij snprintf( sLog, sizeof(sLog), 3518285612Sdelphij JJY_CLOCKSTATS_MESSAGE_DELAY_UNADJUST, 3519285612Sdelphij up->iLoopbackValidCount, MAX_LOOPBACK ) ; 3520285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 3521285612Sdelphij } 3522285612Sdelphij } 3523285612Sdelphij 3524182007Sroberto } 3525182007Sroberto } 3526182007Sroberto 3527285612Sdelphij } else if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength != iLen 3528285612Sdelphij && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) { 3529285612Sdelphij /* Loopback noise ( Unexpected replay ) */ 3530182007Sroberto 3531285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_IGNORE_REPLY, 3532285612Sdelphij pBuf ) ; 3533285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ; 3534182007Sroberto 3535285612Sdelphij } else { 3536285612Sdelphij 3537285612Sdelphij up->bLineError = TRUE ; 3538285612Sdelphij 3539285612Sdelphij snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY, 3540285612Sdelphij pBuf ) ; 3541285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ; 3542285612Sdelphij 3543285612Sdelphij } 3544285612Sdelphij 3545285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3546285612Sdelphij 3547285612Sdelphij} 3548285612Sdelphij 3549285612Sdelphij/******************************/ 3550285612Sdelphijstatic int 3551285612Sdelphijteljjy_conn_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3552285612Sdelphij{ 3553285612Sdelphij 3554294569Sdelphij const char * pCmd ; 3555285612Sdelphij 3556285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_conn_silent" ) ; 3557285612Sdelphij 3558285612Sdelphij if ( up->iClockCommandSeq >= 1 3559285612Sdelphij && up->iClockCommandSeq < TELJJY_COMMAND_START_SKIP_LOOPBACK ) { 3560285612Sdelphij /* Loopback */ 3561182007Sroberto#ifdef DEBUG 3562182007Sroberto if ( debug ) { 3563285612Sdelphij printf( "refclock_jjy.c : teljjy_conn_silent : call teljjy_conn_send\n" ) ; 3564182007Sroberto } 3565182007Sroberto#endif 3566285612Sdelphij if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) { 3567285612Sdelphij up->bLoopbackTimeout[up->iLoopbackCount] = TRUE ; 3568182007Sroberto } 3569285612Sdelphij up->iTeljjySilentTimer = 0 ; 3570285612Sdelphij return teljjy_conn_send( peer, pp, up ) ; 3571285612Sdelphij } else { 3572285612Sdelphij pCmd = "\r" ; 3573285612Sdelphij } 3574182007Sroberto 3575285612Sdelphij if ( write( pp->io.fd, pCmd, 1 ) != 1 ) { 3576285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 3577182007Sroberto } 3578182007Sroberto 3579285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 3580182007Sroberto 3581285612Sdelphij up->iTeljjySilentTimer = 0 ; 3582285612Sdelphij 3583285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3584285612Sdelphij 3585182007Sroberto} 3586182007Sroberto 3587285612Sdelphij/******************************/ 3588285612Sdelphijstatic int 3589285612Sdelphijteljjy_conn_error ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3590285612Sdelphij{ 3591285612Sdelphij 3592285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_conn_error" ) ; 3593285612Sdelphij 3594285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3595285612Sdelphij 3596285612Sdelphij} 3597285612Sdelphij 3598285612Sdelphij/******************************/ 3599285612Sdelphijstatic int 3600285612Sdelphijteljjy_bye_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3601285612Sdelphij{ 3602285612Sdelphij 3603285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_bye_ignore" ) ; 3604285612Sdelphij 3605285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3606285612Sdelphij 3607285612Sdelphij} 3608285612Sdelphij 3609285612Sdelphij/******************************/ 3610285612Sdelphijstatic int 3611285612Sdelphijteljjy_bye_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3612285612Sdelphij{ 3613285612Sdelphij 3614285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_bye_disc" ) ; 3615285612Sdelphij 3616285612Sdelphij return TELJJY_CHANGE_CLOCK_STATE ; 3617285612Sdelphij 3618285612Sdelphij} 3619285612Sdelphij 3620285612Sdelphij/******************************/ 3621285612Sdelphijstatic int 3622285612Sdelphijteljjy_bye_modem ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3623285612Sdelphij{ 3624285612Sdelphij 3625285612Sdelphij DEBUG_TELJJY_PRINTF( "teljjy_bye_modem" ) ; 3626285612Sdelphij 3627285612Sdelphij modem_disconnect ( peer->refclkunit, peer ) ; 3628285612Sdelphij 3629285612Sdelphij return TELJJY_STAY_CLOCK_STATE ; 3630285612Sdelphij 3631285612Sdelphij} 3632285612Sdelphij 3633285612Sdelphij/*################################################################################################*/ 3634285612Sdelphij/*################################################################################################*/ 3635285612Sdelphij/*## ##*/ 3636285612Sdelphij/*## Modem control finite state machine ##*/ 3637285612Sdelphij/*## ##*/ 3638285612Sdelphij/*################################################################################################*/ 3639285612Sdelphij/*################################################################################################*/ 3640285612Sdelphij 3641285612Sdelphij/* struct jjyunit.iModemState */ 3642285612Sdelphij 3643285612Sdelphij#define MODEM_STATE_DISCONNECT 0 3644285612Sdelphij#define MODEM_STATE_INITIALIZE 1 3645285612Sdelphij#define MODEM_STATE_DAILING 2 3646285612Sdelphij#define MODEM_STATE_CONNECT 3 3647285612Sdelphij#define MODEM_STATE_ESCAPE 4 3648285612Sdelphij 3649285612Sdelphij/* struct jjyunit.iModemEvent */ 3650285612Sdelphij 3651285612Sdelphij#define MODEM_EVENT_NULL 0 3652285612Sdelphij#define MODEM_EVENT_INITIALIZE 1 3653285612Sdelphij#define MODEM_EVENT_DIALOUT 2 3654285612Sdelphij#define MODEM_EVENT_DISCONNECT 3 3655285612Sdelphij#define MODEM_EVENT_RESP_OK 4 3656285612Sdelphij#define MODEM_EVENT_RESP_CONNECT 5 3657285612Sdelphij#define MODEM_EVENT_RESP_RING 6 3658285612Sdelphij#define MODEM_EVENT_RESP_NO_CARRIER 7 3659285612Sdelphij#define MODEM_EVENT_RESP_ERROR 8 3660285612Sdelphij#define MODEM_EVENT_RESP_CONNECT_X 9 3661285612Sdelphij#define MODEM_EVENT_RESP_NO_DAILTONE 10 3662285612Sdelphij#define MODEM_EVENT_RESP_BUSY 11 3663285612Sdelphij#define MODEM_EVENT_RESP_NO_ANSWER 12 3664285612Sdelphij#define MODEM_EVENT_RESP_UNKNOWN 13 3665285612Sdelphij#define MODEM_EVENT_SILENT 14 3666285612Sdelphij#define MODEM_EVENT_TIMEOUT 15 3667285612Sdelphij 3668285612Sdelphij/* Function prototypes */ 3669285612Sdelphij 3670285612Sdelphijstatic void modem_control ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3671285612Sdelphij 3672285612Sdelphijstatic int modem_disc_ignore ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3673285612Sdelphijstatic int modem_disc_init ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3674285612Sdelphijstatic int modem_init_ignore ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3675285612Sdelphijstatic int modem_init_start ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3676285612Sdelphijstatic int modem_init_disc ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3677285612Sdelphijstatic int modem_init_resp00 ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3678285612Sdelphijstatic int modem_init_resp04 ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3679285612Sdelphijstatic int modem_dial_ignore ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3680285612Sdelphijstatic int modem_dial_dialout ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3681285612Sdelphijstatic int modem_dial_escape ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3682285612Sdelphijstatic int modem_dial_connect ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3683285612Sdelphijstatic int modem_dial_disc ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3684285612Sdelphijstatic int modem_conn_ignore ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3685285612Sdelphijstatic int modem_conn_escape ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3686285612Sdelphijstatic int modem_esc_ignore ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3687285612Sdelphijstatic int modem_esc_escape ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3688285612Sdelphijstatic int modem_esc_data ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3689285612Sdelphijstatic int modem_esc_silent ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3690285612Sdelphijstatic int modem_esc_disc ( struct peer *, struct refclockproc *, struct jjyunit * ) ; 3691285612Sdelphij 3692294569Sdelphijstatic int ( *pModemHandler [ ] [ 5 ] ) ( struct peer *, struct refclockproc *, struct jjyunit * ) = 3693285612Sdelphij{ /*STATE_DISCONNECT STATE_INITIALIZE STATE_DAILING STATE_CONNECT STATE_ESCAPE */ 3694285612Sdelphij/* NULL */ { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_ignore }, 3695285612Sdelphij/* INITIALIZE */ { modem_disc_init , modem_init_start , modem_dial_ignore , modem_conn_ignore, modem_esc_ignore }, 3696285612Sdelphij/* DIALOUT */ { modem_disc_ignore, modem_init_ignore, modem_dial_dialout, modem_conn_ignore, modem_esc_ignore }, 3697285612Sdelphij/* DISCONNECT */ { modem_disc_ignore, modem_init_disc , modem_dial_escape , modem_conn_escape, modem_esc_escape }, 3698285612Sdelphij/* RESP: 0: OK */ { modem_disc_ignore, modem_init_resp00, modem_dial_ignore , modem_conn_ignore, modem_esc_data }, 3699285612Sdelphij/* RESP: 1: CONNECT */ { modem_disc_ignore, modem_init_ignore, modem_dial_connect, modem_conn_ignore, modem_esc_data }, 3700285612Sdelphij/* RESP: 2: RING */ { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_data }, 3701285612Sdelphij/* RESP: 3: NO CARRIER */ { modem_disc_ignore, modem_init_ignore, modem_dial_disc , modem_conn_ignore, modem_esc_data }, 3702285612Sdelphij/* RESP: 4: ERROR */ { modem_disc_ignore, modem_init_resp04, modem_dial_disc , modem_conn_ignore, modem_esc_data }, 3703285612Sdelphij/* RESP: 5: CONNECT */ { modem_disc_ignore, modem_init_ignore, modem_dial_connect, modem_conn_ignore, modem_esc_data }, 3704285612Sdelphij/* RESP: 6: NO DAILTONE */ { modem_disc_ignore, modem_init_ignore, modem_dial_disc , modem_conn_ignore, modem_esc_data }, 3705285612Sdelphij/* RESP: 7: BUSY */ { modem_disc_ignore, modem_init_ignore, modem_dial_disc , modem_conn_ignore, modem_esc_data }, 3706285612Sdelphij/* RESP: 8: NO ANSWER */ { modem_disc_ignore, modem_init_ignore, modem_dial_disc , modem_conn_ignore, modem_esc_data }, 3707285612Sdelphij/* RESP: 9: UNKNOWN */ { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_data }, 3708285612Sdelphij/* SILENT */ { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_silent }, 3709285612Sdelphij/* TIMEOUT */ { modem_disc_ignore, modem_init_disc , modem_dial_escape , modem_conn_escape, modem_esc_disc } 3710285612Sdelphij} ; 3711285612Sdelphij 3712285612Sdelphijstatic short iModemNextState [ ] [ 5 ] = 3713285612Sdelphij{ /*STATE_DISCONNECT STATE_INITIALIZE STATE_DAILING STATE_CONNECT STATE_ESCAPE */ 3714285612Sdelphij/* NULL */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3715285612Sdelphij/* INITIALIZE */ { MODEM_STATE_INITIALIZE, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3716285612Sdelphij/* DIALOUT */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3717285612Sdelphij/* DISCONNECT */ { MODEM_STATE_DISCONNECT, MODEM_STATE_DISCONNECT, MODEM_STATE_ESCAPE , MODEM_STATE_ESCAPE , MODEM_STATE_ESCAPE }, 3718285612Sdelphij/* RESP: 0: OK */ { MODEM_STATE_DISCONNECT, MODEM_STATE_DAILING , MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3719285612Sdelphij/* RESP: 1: CONNECT */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_CONNECT , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3720285612Sdelphij/* RESP: 2: RING */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3721285612Sdelphij/* RESP: 3: NO CARRIER */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3722285612Sdelphij/* RESP: 4: ERROR */ { MODEM_STATE_DISCONNECT, MODEM_STATE_DAILING , MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3723285612Sdelphij/* RESP: 5: CONNECT X */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_CONNECT , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3724285612Sdelphij/* RESP: 6: NO DAILTONE */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3725285612Sdelphij/* RESP: 7: BUSY */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3726285612Sdelphij/* RESP: 8: NO ANSWER */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3727285612Sdelphij/* RESP: 9: UNKNOWN */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE }, 3728285612Sdelphij/* SILENT */ { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING , MODEM_STATE_CONNECT, MODEM_STATE_DISCONNECT }, 3729285612Sdelphij/* TIMEOUT */ { MODEM_STATE_DISCONNECT, MODEM_STATE_DISCONNECT, MODEM_STATE_ESCAPE , MODEM_STATE_ESCAPE , MODEM_STATE_DISCONNECT } 3730285612Sdelphij} ; 3731285612Sdelphij 3732285612Sdelphijstatic short iModemPostEvent [ ] [ 5 ] = 3733285612Sdelphij{ /*STATE_DISCONNECT STATE_INITIALIZE STATE_DAILING STATE_CONNECT STATE_ESCAPE */ 3734285612Sdelphij/* NULL */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3735285612Sdelphij/* INITIALIZE */ { MODEM_EVENT_INITIALIZE, MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3736285612Sdelphij/* DIALOUT */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3737285612Sdelphij/* DISCONNECT */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_DISCONNECT, MODEM_EVENT_DISCONNECT, MODEM_EVENT_NULL }, 3738285612Sdelphij/* RESP: 0: OK */ { MODEM_EVENT_NULL , MODEM_EVENT_DIALOUT, MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3739285612Sdelphij/* RESP: 1: CONNECT */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3740285612Sdelphij/* RESP: 2: RING */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3741285612Sdelphij/* RESP: 3: NO CARRIER */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3742285612Sdelphij/* RESP: 4: ERROR */ { MODEM_EVENT_NULL , MODEM_EVENT_DIALOUT, MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3743285612Sdelphij/* RESP: 5: CONNECT X */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3744285612Sdelphij/* RESP: 6: NO DAILTONE */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3745285612Sdelphij/* RESP: 7: BUSY */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3746285612Sdelphij/* RESP: 8: NO ANSWER */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3747285612Sdelphij/* RESP: 9: UNKNOWN */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3748285612Sdelphij/* SILENT */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_NULL }, 3749285612Sdelphij/* TIMEOUT */ { MODEM_EVENT_NULL , MODEM_EVENT_NULL , MODEM_EVENT_DISCONNECT, MODEM_EVENT_DISCONNECT, MODEM_EVENT_NULL } 3750285612Sdelphij} ; 3751285612Sdelphij 3752285612Sdelphijstatic short iModemSilentTimeout [ 5 ] = { 0, 0, 0, 0, 5 } ; 3753285612Sdelphijstatic short iModemStateTimeout [ 5 ] = { 0, 20, 90, 0, 20 } ; 3754285612Sdelphij 3755285612Sdelphij#define STAY_MODEM_STATE 0 3756285612Sdelphij#define CHANGE_MODEM_STATE 1 3757285612Sdelphij 3758285612Sdelphij#ifdef DEBUG 3759285612Sdelphij#define DEBUG_MODEM_PRINTF(sFunc) { if ( debug ) { printf ( "refclock_jjy.c : %s : iModemState=%d iModemEvent=%d iModemSilentTimer=%d iModemStateTimer=%d\n", sFunc, up->iModemState, up->iModemEvent, up->iModemSilentTimer, up->iModemStateTimer ) ; } } 3760285612Sdelphij#else 3761285612Sdelphij#define DEBUG_MODEM_PRINTF(sFunc) 3762285612Sdelphij#endif 3763285612Sdelphij 3764182007Sroberto/**************************************************************************************************/ 3765200576Sroberto 3766285612Sdelphijstatic short 3767285612SdelphijgetModemState ( struct jjyunit *up ) 3768285612Sdelphij{ 3769285612Sdelphij return up->iModemState ; 3770285612Sdelphij} 3771285612Sdelphij 3772285612Sdelphij/**************************************************************************************************/ 3773285612Sdelphij 3774200576Srobertostatic int 3775285612SdelphijisModemStateConnect ( short iCheckState ) 3776200576Sroberto{ 3777285612Sdelphij return ( iCheckState == MODEM_STATE_CONNECT ) ; 3778285612Sdelphij} 3779200576Sroberto 3780285612Sdelphij/**************************************************************************************************/ 3781200576Sroberto 3782285612Sdelphijstatic int 3783285612SdelphijisModemStateDisconnect ( short iCheckState ) 3784285612Sdelphij{ 3785285612Sdelphij return ( iCheckState == MODEM_STATE_DISCONNECT ) ; 3786285612Sdelphij} 3787200576Sroberto 3788285612Sdelphij/**************************************************************************************************/ 3789200576Sroberto 3790285612Sdelphijstatic int 3791285612SdelphijisModemStateTimerOn ( struct jjyunit *up ) 3792285612Sdelphij{ 3793285612Sdelphij return ( iModemSilentTimeout[up->iModemState] != 0 || iModemStateTimeout[up->iModemState] != 0 ) ; 3794285612Sdelphij} 3795200576Sroberto 3796285612Sdelphij/**************************************************************************************************/ 3797200576Sroberto 3798285612Sdelphijstatic void 3799285612Sdelphijmodem_connect ( int unit, struct peer *peer ) 3800285612Sdelphij{ 3801285612Sdelphij struct refclockproc *pp; 3802285612Sdelphij struct jjyunit *up; 3803200576Sroberto 3804285612Sdelphij pp = peer->procptr ; 3805285612Sdelphij up = pp->unitptr ; 3806200576Sroberto 3807285612Sdelphij DEBUG_MODEM_PRINTF( "modem_connect" ) ; 3808200576Sroberto 3809285612Sdelphij up->iModemEvent = MODEM_EVENT_INITIALIZE ; 3810285612Sdelphij 3811285612Sdelphij modem_control ( peer, pp, up ) ; 3812285612Sdelphij 3813285612Sdelphij} 3814285612Sdelphij 3815285612Sdelphij/**************************************************************************************************/ 3816285612Sdelphij 3817285612Sdelphijstatic void 3818285612Sdelphijmodem_disconnect ( int unit, struct peer *peer ) 3819285612Sdelphij{ 3820285612Sdelphij struct refclockproc *pp; 3821285612Sdelphij struct jjyunit *up; 3822285612Sdelphij 3823285612Sdelphij pp = peer->procptr ; 3824285612Sdelphij up = pp->unitptr ; 3825285612Sdelphij 3826285612Sdelphij DEBUG_MODEM_PRINTF( "modem_disconnect" ) ; 3827285612Sdelphij 3828285612Sdelphij up->iModemEvent = MODEM_EVENT_DISCONNECT ; 3829285612Sdelphij 3830285612Sdelphij modem_control ( peer, pp, up ) ; 3831285612Sdelphij 3832285612Sdelphij} 3833285612Sdelphij 3834285612Sdelphij/**************************************************************************************************/ 3835285612Sdelphij 3836285612Sdelphijstatic int 3837285612Sdelphijmodem_receive ( struct recvbuf *rbufp ) 3838285612Sdelphij{ 3839285612Sdelphij 3840285612Sdelphij struct peer *peer; 3841285612Sdelphij struct jjyunit *up; 3842285612Sdelphij struct refclockproc *pp; 3843285612Sdelphij char *pBuf ; 3844316722Sdelphij size_t iLen ; 3845285612Sdelphij 3846200576Sroberto#ifdef DEBUG 3847285612Sdelphij static const char *sFunctionName = "modem_receive" ; 3848200576Sroberto#endif 3849200576Sroberto 3850285612Sdelphij peer = rbufp->recv_peer ; 3851285612Sdelphij pp = peer->procptr ; 3852285612Sdelphij up = pp->unitptr ; 3853285612Sdelphij 3854285612Sdelphij DEBUG_MODEM_PRINTF( sFunctionName ) ; 3855285612Sdelphij 3856285612Sdelphij if ( up->linediscipline == LDISC_RAW ) { 3857285612Sdelphij pBuf = up->sTextBuf ; 3858285612Sdelphij iLen = up->iTextBufLen ; 3859285612Sdelphij } else { 3860285612Sdelphij pBuf = pp->a_lastcode ; 3861285612Sdelphij iLen = pp->lencode ; 3862285612Sdelphij } 3863285612Sdelphij 3864285612Sdelphij if ( iLen == 2 && strncmp( pBuf, "OK" , 2 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_OK ; } 3865285612Sdelphij else if ( iLen == 7 && strncmp( pBuf, "CONNECT" , 7 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_CONNECT ; } 3866285612Sdelphij else if ( iLen == 4 && strncmp( pBuf, "RING" , 4 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_RING ; } 3867285612Sdelphij else if ( iLen == 10 && strncmp( pBuf, "NO CARRIER" , 10 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_CARRIER ; } 3868285612Sdelphij else if ( iLen == 5 && strncmp( pBuf, "ERROR" , 5 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_ERROR ; } 3869285612Sdelphij else if ( iLen >= 8 && strncmp( pBuf, "CONNECT " , 8 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_CONNECT_X ; } 3870285612Sdelphij else if ( iLen == 11 && strncmp( pBuf, "NO DAILTONE", 11 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_DAILTONE ; } 3871285612Sdelphij else if ( iLen == 4 && strncmp( pBuf, "BUSY" , 4 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_BUSY ; } 3872285612Sdelphij else if ( iLen == 9 && strncmp( pBuf, "NO ANSWER" , 9 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_ANSWER ; } 3873285612Sdelphij else { up->iModemEvent = MODEM_EVENT_RESP_UNKNOWN ; } 3874285612Sdelphij 3875200576Sroberto#ifdef DEBUG 3876285612Sdelphij if ( debug ) { 3877285612Sdelphij char sResp [ 40 ] ; 3878316722Sdelphij size_t iCopyLen ; 3879285612Sdelphij iCopyLen = ( iLen <= sizeof(sResp)-1 ? iLen : sizeof(sResp)-1 ) ; 3880285612Sdelphij strncpy( sResp, pBuf, iLen <= sizeof(sResp)-1 ? iLen : sizeof(sResp)-1 ) ; 3881285612Sdelphij sResp[iCopyLen] = 0 ; 3882316722Sdelphij printf ( "refclock_jjy.c : modem_receive : iLen=%zu pBuf=[%s] iModemEvent=%d\n", iCopyLen, sResp, up->iModemEvent ) ; 3883285612Sdelphij } 3884200576Sroberto#endif 3885285612Sdelphij modem_control ( peer, pp, up ) ; 3886200576Sroberto 3887285612Sdelphij return 0 ; 3888200576Sroberto 3889285612Sdelphij} 3890200576Sroberto 3891285612Sdelphij/**************************************************************************************************/ 3892200576Sroberto 3893285612Sdelphijstatic void 3894285612Sdelphijmodem_timer ( int unit, struct peer *peer ) 3895285612Sdelphij{ 3896200576Sroberto 3897285612Sdelphij struct refclockproc *pp ; 3898285612Sdelphij struct jjyunit *up ; 3899200576Sroberto 3900285612Sdelphij pp = peer->procptr ; 3901285612Sdelphij up = pp->unitptr ; 3902200576Sroberto 3903285612Sdelphij DEBUG_MODEM_PRINTF( "modem_timer" ) ; 3904285612Sdelphij 3905285612Sdelphij if ( iModemSilentTimeout[up->iModemState] != 0 ) { 3906285612Sdelphij up->iModemSilentTimer++ ; 3907285612Sdelphij if ( iModemSilentTimeout[up->iModemState] <= up->iModemSilentTimer ) { 3908285612Sdelphij up->iModemEvent = MODEM_EVENT_SILENT ; 3909285612Sdelphij modem_control ( peer, pp, up ) ; 3910285612Sdelphij } 3911285612Sdelphij } 3912285612Sdelphij 3913285612Sdelphij if ( iModemStateTimeout[up->iModemState] != 0 ) { 3914285612Sdelphij up->iModemStateTimer++ ; 3915285612Sdelphij if ( iModemStateTimeout[up->iModemState] <= up->iModemStateTimer ) { 3916285612Sdelphij up->iModemEvent = MODEM_EVENT_TIMEOUT ; 3917285612Sdelphij modem_control ( peer, pp, up ) ; 3918285612Sdelphij } 3919285612Sdelphij } 3920285612Sdelphij 3921200576Sroberto} 3922200576Sroberto 3923200576Sroberto/**************************************************************************************************/ 3924285612Sdelphij 3925106163Srobertostatic void 3926285612Sdelphijmodem_control ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3927106163Sroberto{ 3928106163Sroberto 3929285612Sdelphij int rc ; 3930285612Sdelphij short iPostEvent = MODEM_EVENT_NULL ; 3931106163Sroberto 3932285612Sdelphij DEBUG_MODEM_PRINTF( "modem_control" ) ; 3933106163Sroberto 3934285612Sdelphij rc = (*pModemHandler[up->iModemEvent][up->iModemState])( peer, pp, up ) ; 3935285612Sdelphij 3936285612Sdelphij if ( rc == CHANGE_MODEM_STATE ) { 3937285612Sdelphij iPostEvent = iModemPostEvent[up->iModemEvent][up->iModemState] ; 3938285612Sdelphij#ifdef DEBUG 3939285612Sdelphij if ( debug ) { 3940285612Sdelphij printf( "refclock_jjy.c : modem_control : iModemState=%d -> %d iPostEvent=%d\n", 3941285612Sdelphij up->iModemState, iModemNextState[up->iModemEvent][up->iModemState], iPostEvent ) ; 3942285612Sdelphij } 3943285612Sdelphij#endif 3944285612Sdelphij 3945285612Sdelphij if ( up->iModemState != iModemNextState[up->iModemEvent][up->iModemState] ) { 3946285612Sdelphij up->iModemSilentCount = 0 ; 3947285612Sdelphij up->iModemStateTimer = 0 ; 3948285612Sdelphij up->iModemCommandSeq = 0 ; 3949285612Sdelphij } 3950285612Sdelphij 3951285612Sdelphij up->iModemState = iModemNextState[up->iModemEvent][up->iModemState] ; 3952106163Sroberto } 3953106163Sroberto 3954285612Sdelphij if ( iPostEvent != MODEM_EVENT_NULL ) { 3955285612Sdelphij up->iModemEvent = iPostEvent ; 3956285612Sdelphij modem_control ( peer, pp, up ) ; 3957285612Sdelphij } 3958285612Sdelphij 3959285612Sdelphij up->iModemEvent = MODEM_EVENT_NULL ; 3960285612Sdelphij 3961285612Sdelphij} 3962285612Sdelphij 3963285612Sdelphij/******************************/ 3964285612Sdelphijstatic int 3965285612Sdelphijmodem_disc_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3966285612Sdelphij{ 3967285612Sdelphij 3968285612Sdelphij DEBUG_MODEM_PRINTF( "modem_disc_ignore" ) ; 3969285612Sdelphij 3970285612Sdelphij return STAY_MODEM_STATE ; 3971285612Sdelphij 3972285612Sdelphij} 3973285612Sdelphij 3974285612Sdelphij/******************************/ 3975285612Sdelphijstatic int 3976285612Sdelphijmodem_disc_init ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3977285612Sdelphij{ 3978285612Sdelphij 3979285612Sdelphij DEBUG_MODEM_PRINTF( "modem_disc_init" ) ; 3980285612Sdelphij 3981285612Sdelphij return CHANGE_MODEM_STATE ; 3982285612Sdelphij 3983285612Sdelphij} 3984285612Sdelphij 3985285612Sdelphij/******************************/ 3986285612Sdelphijstatic int 3987285612Sdelphijmodem_init_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3988285612Sdelphij{ 3989285612Sdelphij 3990285612Sdelphij DEBUG_MODEM_PRINTF( "modem_init_ignore" ) ; 3991285612Sdelphij 3992285612Sdelphij return STAY_MODEM_STATE ; 3993285612Sdelphij 3994285612Sdelphij} 3995285612Sdelphij 3996285612Sdelphij/******************************/ 3997285612Sdelphijstatic int 3998285612Sdelphijmodem_init_start ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 3999285612Sdelphij{ 4000285612Sdelphij 4001285612Sdelphij DEBUG_MODEM_PRINTF( "modem_init_start" ) ; 4002285612Sdelphij 4003285612Sdelphij up->iModemCommandSeq = 0 ; 4004285612Sdelphij 4005106163Sroberto#ifdef DEBUG 4006106163Sroberto if ( debug ) { 4007285612Sdelphij printf( "refclock_jjy.c : modem_init_start : call modem_init_resp00\n" ) ; 4008106163Sroberto } 4009106163Sroberto#endif 4010106163Sroberto 4011285612Sdelphij return modem_init_resp00( peer, pp, up ) ; 4012106163Sroberto 4013285612Sdelphij} 4014106163Sroberto 4015285612Sdelphij/******************************/ 4016285612Sdelphijstatic int 4017285612Sdelphijmodem_init_resp00 ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4018285612Sdelphij{ 4019285612Sdelphij 4020294569Sdelphij const char * pCmd ; 4021294569Sdelphij char cBuf [ 46 ] ; 4022294569Sdelphij int iCmdLen ; 4023294569Sdelphij int iErrorCorrection, iSpeakerSwitch, iSpeakerVolume ; 4024294569Sdelphij int iNextModemState = STAY_MODEM_STATE ; 4025285612Sdelphij 4026285612Sdelphij DEBUG_MODEM_PRINTF( "modem_init_resp00" ) ; 4027285612Sdelphij 4028285612Sdelphij up->iModemCommandSeq++ ; 4029285612Sdelphij 4030285612Sdelphij switch ( up->iModemCommandSeq ) { 4031285612Sdelphij 4032285612Sdelphij case 1 : 4033285612Sdelphij /* En = Echoback 0:Off 1:On */ 4034285612Sdelphij /* Qn = Result codes 0:On 1:Off */ 4035285612Sdelphij /* Vn = Result codes 0:Numeric 1:Text */ 4036285612Sdelphij pCmd = "ATE0Q0V1\r\n" ; 4037106163Sroberto break ; 4038106163Sroberto 4039285612Sdelphij case 2 : 4040285612Sdelphij /* Mn = Speaker switch 0:Off 1:On until remote carrier detected 2:On */ 4041285612Sdelphij if ( ( pp->sloppyclockflag & CLK_FLAG3 ) == 0 ) { 4042285612Sdelphij /* fudge 127.127.40.n flag3 0 */ 4043285612Sdelphij iSpeakerSwitch = 0 ; 4044285612Sdelphij } else { 4045285612Sdelphij /* fudge 127.127.40.n flag3 1 */ 4046285612Sdelphij iSpeakerSwitch = 2 ; 4047285612Sdelphij } 4048285612Sdelphij 4049285612Sdelphij /* Ln = Speaker volume 0:Very low 1:Low 2:Middle 3:High */ 4050285612Sdelphij if ( ( pp->sloppyclockflag & CLK_FLAG4 ) == 0 ) { 4051285612Sdelphij /* fudge 127.127.40.n flag4 0 */ 4052285612Sdelphij iSpeakerVolume = 1 ; 4053285612Sdelphij } else { 4054285612Sdelphij /* fudge 127.127.40.n flag4 1 */ 4055285612Sdelphij iSpeakerVolume = 2 ; 4056285612Sdelphij } 4057285612Sdelphij 4058285612Sdelphij pCmd = cBuf ; 4059294569Sdelphij snprintf( cBuf, sizeof(cBuf), "ATM%dL%d\r\n", iSpeakerSwitch, iSpeakerVolume ) ; 4060106163Sroberto break ; 4061106163Sroberto 4062285612Sdelphij case 3 : 4063285612Sdelphij /* &Kn = Flow control 4:XON/XOFF */ 4064285612Sdelphij pCmd = "AT&K4\r\n" ; 4065182007Sroberto break ; 4066182007Sroberto 4067285612Sdelphij case 4 : 4068285612Sdelphij /* +MS = Protocol V22B:1200,2400bps�iV.22bis) */ 4069285612Sdelphij pCmd = "AT+MS=V22B\r\n" ; 4070285612Sdelphij break ; 4071200576Sroberto 4072285612Sdelphij case 5 : 4073285612Sdelphij /* %Cn = Data compression 0:No data compression */ 4074285612Sdelphij pCmd = "AT%C0\r\n" ; 4075285612Sdelphij break ; 4076285612Sdelphij 4077285612Sdelphij case 6 : 4078285612Sdelphij /* \Nn = Error correction 0:Normal mode 1:Direct mode 2:V42,MNP 3:V42,MNP,Normal */ 4079285612Sdelphij if ( ( pp->sloppyclockflag & CLK_FLAG2 ) == 0 ) { 4080285612Sdelphij /* fudge 127.127.40.n flag2 0 */ 4081285612Sdelphij iErrorCorrection = 0 ; 4082285612Sdelphij } else { 4083285612Sdelphij /* fudge 127.127.40.n flag2 1 */ 4084285612Sdelphij iErrorCorrection = 3 ; 4085285612Sdelphij } 4086285612Sdelphij 4087285612Sdelphij pCmd = cBuf ; 4088294569Sdelphij snprintf( cBuf, sizeof(cBuf), "AT\\N%d\r\n", iErrorCorrection ) ; 4089285612Sdelphij break ; 4090285612Sdelphij 4091285612Sdelphij case 7 : 4092285612Sdelphij /* Hn = Hook 0:Hook-On ( Disconnect ) 1:Hook-Off ( Connect ) */ 4093285612Sdelphij pCmd = "ATH1\r\n" ; 4094285612Sdelphij break ; 4095285612Sdelphij 4096285612Sdelphij case 8 : 4097285612Sdelphij /* Initialize completion */ 4098285612Sdelphij pCmd = NULL ; 4099285612Sdelphij iNextModemState = CHANGE_MODEM_STATE ; 4100285612Sdelphij break ; 4101285612Sdelphij 4102106163Sroberto default : 4103285612Sdelphij pCmd = NULL ; 4104106163Sroberto break ; 4105106163Sroberto 4106106163Sroberto } 4107106163Sroberto 4108285612Sdelphij if ( pCmd != NULL ) { 4109285612Sdelphij 4110285612Sdelphij iCmdLen = strlen( pCmd ) ; 4111285612Sdelphij if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 4112285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 4113285612Sdelphij } 4114285612Sdelphij 4115285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 4116285612Sdelphij 4117285612Sdelphij } 4118285612Sdelphij 4119285612Sdelphij return iNextModemState ; 4120285612Sdelphij 4121106163Sroberto} 4122106163Sroberto 4123285612Sdelphij/******************************/ 4124285612Sdelphijstatic int 4125285612Sdelphijmodem_init_resp04 ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4126106163Sroberto{ 4127106163Sroberto 4128285612Sdelphij DEBUG_MODEM_PRINTF( "modem_init_resp04" ) ; 4129106163Sroberto 4130285612Sdelphij return modem_init_resp00( peer, pp, up ) ; 4131106163Sroberto 4132285612Sdelphij} 4133106163Sroberto 4134285612Sdelphij/******************************/ 4135285612Sdelphijstatic int 4136285612Sdelphijmodem_init_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4137285612Sdelphij{ 4138285612Sdelphij 4139285612Sdelphij DEBUG_MODEM_PRINTF( "modem_init_disc" ) ; 4140182007Sroberto#ifdef DEBUG 4141182007Sroberto if ( debug ) { 4142285612Sdelphij printf( "refclock_jjy.c : modem_init_disc : call modem_esc_disc\n" ) ; 4143182007Sroberto } 4144182007Sroberto#endif 4145182007Sroberto 4146285612Sdelphij return CHANGE_MODEM_STATE ; 4147106163Sroberto 4148182007Sroberto} 4149182007Sroberto 4150285612Sdelphij/******************************/ 4151285612Sdelphijstatic int 4152285612Sdelphijmodem_dial_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4153285612Sdelphij{ 4154182007Sroberto 4155285612Sdelphij DEBUG_MODEM_PRINTF( "modem_dial_ignore" ) ; 4156285612Sdelphij 4157285612Sdelphij return STAY_MODEM_STATE ; 4158285612Sdelphij 4159285612Sdelphij} 4160285612Sdelphij 4161285612Sdelphij/******************************/ 4162285612Sdelphijstatic int 4163285612Sdelphijmodem_dial_dialout ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4164182007Sroberto{ 4165182007Sroberto 4166285612Sdelphij char sCmd [ 46 ] ; 4167285612Sdelphij int iCmdLen ; 4168285612Sdelphij char cToneOrPulse ; 4169182007Sroberto 4170285612Sdelphij DEBUG_MODEM_PRINTF( "modem_dial_dialout" ) ; 4171182007Sroberto 4172285612Sdelphij /* Tone or Pulse */ 4173285612Sdelphij if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) { 4174285612Sdelphij /* fudge 127.127.40.n flag1 0 */ 4175285612Sdelphij cToneOrPulse = 'T' ; 4176285612Sdelphij } else { 4177285612Sdelphij /* fudge 127.127.40.n flag1 1 */ 4178285612Sdelphij cToneOrPulse = 'P' ; 4179285612Sdelphij } 4180106163Sroberto 4181285612Sdelphij /* Connect ( Dial number ) */ 4182285612Sdelphij snprintf( sCmd, sizeof(sCmd), "ATDW%c%s\r\n", cToneOrPulse, *sys_phone ) ; 4183285612Sdelphij 4184285612Sdelphij /* Send command */ 4185285612Sdelphij iCmdLen = strlen( sCmd ) ; 4186285612Sdelphij if ( write( pp->io.fd, sCmd, iCmdLen ) != iCmdLen ) { 4187285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 4188285612Sdelphij } 4189285612Sdelphij 4190285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, sCmd ) ; 4191285612Sdelphij 4192285612Sdelphij return STAY_MODEM_STATE ; 4193285612Sdelphij 4194285612Sdelphij} 4195285612Sdelphij 4196285612Sdelphij/******************************/ 4197285612Sdelphijstatic int 4198285612Sdelphijmodem_dial_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4199285612Sdelphij{ 4200285612Sdelphij 4201285612Sdelphij DEBUG_MODEM_PRINTF( "modem_dial_escape" ) ; 4202182007Sroberto#ifdef DEBUG 4203182007Sroberto if ( debug ) { 4204285612Sdelphij printf( "refclock_jjy.c : modem_dial_escape : call modem_conn_escape\n" ) ; 4205106163Sroberto } 4206182007Sroberto#endif 4207106163Sroberto 4208285612Sdelphij return modem_conn_escape( peer, pp, up ) ; 4209285612Sdelphij 4210285612Sdelphij} 4211285612Sdelphij 4212285612Sdelphij/******************************/ 4213285612Sdelphijstatic int 4214285612Sdelphijmodem_dial_connect ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4215285612Sdelphij{ 4216285612Sdelphij 4217285612Sdelphij DEBUG_MODEM_PRINTF( "modem_dial_connect" ) ; 4218285612Sdelphij 4219285612Sdelphij return CHANGE_MODEM_STATE ; 4220285612Sdelphij 4221285612Sdelphij} 4222285612Sdelphij 4223285612Sdelphij/******************************/ 4224285612Sdelphijstatic int 4225285612Sdelphijmodem_dial_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4226285612Sdelphij{ 4227285612Sdelphij 4228285612Sdelphij DEBUG_MODEM_PRINTF( "modem_dial_disc" ) ; 4229285612Sdelphij#ifdef DEBUG 4230285612Sdelphij if ( debug ) { 4231285612Sdelphij printf( "refclock_jjy.c : modem_dial_disc : call modem_esc_disc\n" ) ; 4232182007Sroberto } 4233285612Sdelphij#endif 4234182007Sroberto 4235285612Sdelphij modem_esc_disc( peer, pp, up ) ; 4236285612Sdelphij 4237285612Sdelphij return CHANGE_MODEM_STATE ; 4238285612Sdelphij 4239106163Sroberto} 4240106163Sroberto 4241285612Sdelphij/******************************/ 4242285612Sdelphijstatic int 4243285612Sdelphijmodem_conn_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4244285612Sdelphij{ 4245106163Sroberto 4246285612Sdelphij DEBUG_MODEM_PRINTF( "modem_conn_ignore" ) ; 4247285612Sdelphij 4248285612Sdelphij return STAY_MODEM_STATE ; 4249285612Sdelphij 4250285612Sdelphij} 4251285612Sdelphij 4252285612Sdelphij/******************************/ 4253285612Sdelphijstatic int 4254285612Sdelphijmodem_conn_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4255106163Sroberto{ 4256106163Sroberto 4257285612Sdelphij DEBUG_MODEM_PRINTF( "modem_conn_escape" ) ; 4258106163Sroberto 4259285612Sdelphij return CHANGE_MODEM_STATE ; 4260182007Sroberto 4261285612Sdelphij} 4262106163Sroberto 4263285612Sdelphij/******************************/ 4264285612Sdelphijstatic int 4265285612Sdelphijmodem_esc_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4266285612Sdelphij{ 4267106163Sroberto 4268285612Sdelphij DEBUG_MODEM_PRINTF( "modem_esc_ignore" ) ; 4269285612Sdelphij 4270285612Sdelphij return STAY_MODEM_STATE ; 4271285612Sdelphij 4272285612Sdelphij} 4273285612Sdelphij 4274285612Sdelphij/******************************/ 4275285612Sdelphijstatic int 4276285612Sdelphijmodem_esc_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4277285612Sdelphij{ 4278285612Sdelphij 4279294569Sdelphij const char * pCmd ; 4280294569Sdelphij int iCmdLen ; 4281285612Sdelphij 4282285612Sdelphij DEBUG_MODEM_PRINTF( "modem_esc_escape" ) ; 4283285612Sdelphij 4284285612Sdelphij /* Escape command ( Go to command mode ) */ 4285285612Sdelphij pCmd = "+++" ; 4286285612Sdelphij 4287285612Sdelphij /* Send command */ 4288285612Sdelphij iCmdLen = strlen( pCmd ) ; 4289285612Sdelphij if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 4290285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 4291182007Sroberto } 4292182007Sroberto 4293285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 4294285612Sdelphij 4295285612Sdelphij return STAY_MODEM_STATE ; 4296285612Sdelphij 4297285612Sdelphij} 4298285612Sdelphij 4299285612Sdelphij/******************************/ 4300285612Sdelphijstatic int 4301285612Sdelphijmodem_esc_data ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4302285612Sdelphij{ 4303285612Sdelphij 4304285612Sdelphij DEBUG_MODEM_PRINTF( "modem_esc_data" ) ; 4305285612Sdelphij 4306285612Sdelphij up->iModemSilentTimer = 0 ; 4307285612Sdelphij 4308285612Sdelphij return STAY_MODEM_STATE ; 4309285612Sdelphij 4310285612Sdelphij} 4311285612Sdelphij 4312285612Sdelphij/******************************/ 4313285612Sdelphijstatic int 4314285612Sdelphijmodem_esc_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4315285612Sdelphij{ 4316285612Sdelphij 4317285612Sdelphij DEBUG_MODEM_PRINTF( "modem_esc_silent" ) ; 4318285612Sdelphij 4319285612Sdelphij up->iModemSilentCount ++ ; 4320285612Sdelphij 4321285612Sdelphij if ( up->iModemSilentCount < iModemStateTimeout[up->iModemState] / iModemSilentTimeout[up->iModemState] ) { 4322182007Sroberto#ifdef DEBUG 4323285612Sdelphij if ( debug ) { 4324285612Sdelphij printf( "refclock_jjy.c : modem_esc_silent : call modem_esc_escape\n" ) ; 4325285612Sdelphij } 4326285612Sdelphij#endif 4327285612Sdelphij modem_esc_escape( peer, pp, up ) ; 4328285612Sdelphij up->iModemSilentTimer = 0 ; 4329285612Sdelphij return STAY_MODEM_STATE ; 4330285612Sdelphij } 4331285612Sdelphij 4332285612Sdelphij#ifdef DEBUG 4333182007Sroberto if ( debug ) { 4334285612Sdelphij printf( "refclock_jjy.c : modem_esc_silent : call modem_esc_disc\n" ) ; 4335182007Sroberto } 4336182007Sroberto#endif 4337285612Sdelphij return modem_esc_disc( peer, pp, up ) ; 4338182007Sroberto 4339285612Sdelphij} 4340285612Sdelphij/******************************/ 4341285612Sdelphijstatic int 4342285612Sdelphijmodem_esc_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up ) 4343285612Sdelphij{ 4344285612Sdelphij 4345294569Sdelphij const char * pCmd ; 4346294569Sdelphij int iCmdLen ; 4347285612Sdelphij 4348285612Sdelphij DEBUG_MODEM_PRINTF( "modem_esc_disc" ) ; 4349285612Sdelphij 4350285612Sdelphij /* Disconnect */ 4351285612Sdelphij pCmd = "ATH0\r\n" ; 4352285612Sdelphij 4353285612Sdelphij /* Send command */ 4354285612Sdelphij iCmdLen = strlen( pCmd ) ; 4355285612Sdelphij if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) { 4356285612Sdelphij refclock_report( peer, CEVNT_FAULT ) ; 4357106163Sroberto } 4358106163Sroberto 4359285612Sdelphij jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ; 4360285612Sdelphij 4361285612Sdelphij return CHANGE_MODEM_STATE ; 4362285612Sdelphij 4363106163Sroberto} 4364106163Sroberto 4365285612Sdelphij/*################################################################################################*/ 4366285612Sdelphij/*################################################################################################*/ 4367285612Sdelphij/*## ##*/ 4368285612Sdelphij/*## jjy_write_clockstats ##*/ 4369285612Sdelphij/*## ##*/ 4370285612Sdelphij/*################################################################################################*/ 4371285612Sdelphij/*################################################################################################*/ 4372200576Sroberto 4373200576Srobertostatic void 4374285612Sdelphijjjy_write_clockstats ( struct peer *peer, int iMark, const char *pData ) 4375200576Sroberto{ 4376200576Sroberto 4377294569Sdelphij char sLog [ 100 ] ; 4378294569Sdelphij const char * pMark ; 4379294569Sdelphij int iMarkLen, iDataLen ; 4380200576Sroberto 4381285612Sdelphij switch ( iMark ) { 4382285612Sdelphij case JJY_CLOCKSTATS_MARK_JJY : 4383285612Sdelphij pMark = "JJY " ; 4384285612Sdelphij break ; 4385285612Sdelphij case JJY_CLOCKSTATS_MARK_SEND : 4386285612Sdelphij pMark = "--> " ; 4387285612Sdelphij break ; 4388285612Sdelphij case JJY_CLOCKSTATS_MARK_RECEIVE : 4389285612Sdelphij pMark = "<-- " ; 4390285612Sdelphij break ; 4391285612Sdelphij case JJY_CLOCKSTATS_MARK_INFORMATION : 4392285612Sdelphij pMark = "--- " ; 4393285612Sdelphij break ; 4394285612Sdelphij case JJY_CLOCKSTATS_MARK_ATTENTION : 4395285612Sdelphij pMark = "=== " ; 4396285612Sdelphij break ; 4397285612Sdelphij case JJY_CLOCKSTATS_MARK_WARNING : 4398285612Sdelphij pMark = "-W- " ; 4399285612Sdelphij break ; 4400285612Sdelphij case JJY_CLOCKSTATS_MARK_ERROR : 4401285612Sdelphij pMark = "-X- " ; 4402285612Sdelphij break ; 4403330567Sgordon case JJY_CLOCKSTATS_MARK_BUG : 4404330567Sgordon pMark = "!!! " ; 4405330567Sgordon break ; 4406285612Sdelphij default : 4407285612Sdelphij pMark = "" ; 4408285612Sdelphij break ; 4409285612Sdelphij } 4410285612Sdelphij 4411285612Sdelphij iDataLen = strlen( pData ) ; 4412285612Sdelphij iMarkLen = strlen( pMark ) ; 4413285612Sdelphij strcpy( sLog, pMark ) ; /* Harmless because of enough length */ 4414285612Sdelphij printableString( sLog+iMarkLen, sizeof(sLog)-iMarkLen, pData, iDataLen ) ; 4415285612Sdelphij 4416285612Sdelphij#ifdef DEBUG 4417285612Sdelphij if ( debug ) { 4418285612Sdelphij printf( "refclock_jjy.c : clockstats : %s\n", sLog ) ; 4419285612Sdelphij } 4420285612Sdelphij#endif 4421285612Sdelphij record_clock_stats( &peer->srcadr, sLog ) ; 4422285612Sdelphij 4423200576Sroberto} 4424200576Sroberto 4425285612Sdelphij/*################################################################################################*/ 4426285612Sdelphij/*################################################################################################*/ 4427285612Sdelphij/*## ##*/ 4428285612Sdelphij/*## printableString ##*/ 4429285612Sdelphij/*## ##*/ 4430285612Sdelphij/*################################################################################################*/ 4431285612Sdelphij/*################################################################################################*/ 4432285612Sdelphij 4433285612Sdelphijstatic void 4434285612SdelphijprintableString ( char *sOutput, int iOutputLen, const char *sInput, int iInputLen ) 4435285612Sdelphij{ 4436285612Sdelphij const char *printableControlChar[] = { 4437285612Sdelphij "<NUL>", "<SOH>", "<STX>", "<ETX>", 4438285612Sdelphij "<EOT>", "<ENQ>", "<ACK>", "<BEL>", 4439285612Sdelphij "<BS>" , "<HT>" , "<LF>" , "<VT>" , 4440285612Sdelphij "<FF>" , "<CR>" , "<SO>" , "<SI>" , 4441285612Sdelphij "<DLE>", "<DC1>", "<DC2>", "<DC3>", 4442285612Sdelphij "<DC4>", "<NAK>", "<SYN>", "<ETB>", 4443285612Sdelphij "<CAN>", "<EM>" , "<SUB>", "<ESC>", 4444285612Sdelphij "<FS>" , "<GS>" , "<RS>" , "<US>" , 4445285612Sdelphij " " } ; 4446285612Sdelphij 4447285612Sdelphij size_t i, j, n ; 4448285612Sdelphij size_t InputLen; 4449285612Sdelphij size_t OutputLen; 4450285612Sdelphij 4451285612Sdelphij InputLen = (size_t)iInputLen; 4452285612Sdelphij OutputLen = (size_t)iOutputLen; 4453285612Sdelphij for ( i = j = 0 ; i < InputLen && j < OutputLen ; i ++ ) { 4454285612Sdelphij if ( isprint( (unsigned char)sInput[i] ) ) { 4455285612Sdelphij n = 1 ; 4456285612Sdelphij if ( j + 1 >= OutputLen ) 4457285612Sdelphij break ; 4458285612Sdelphij sOutput[j] = sInput[i] ; 4459285612Sdelphij } else if ( ( sInput[i] & 0xFF ) < 4460285612Sdelphij COUNTOF(printableControlChar) ) { 4461285612Sdelphij n = strlen( printableControlChar[sInput[i] & 0xFF] ) ; 4462285612Sdelphij if ( j + n + 1 >= OutputLen ) 4463285612Sdelphij break ; 4464285612Sdelphij strlcpy( sOutput + j, 4465285612Sdelphij printableControlChar[sInput[i] & 0xFF], 4466285612Sdelphij OutputLen - j ) ; 4467285612Sdelphij } else { 4468285612Sdelphij n = 5 ; 4469285612Sdelphij if ( j + n + 1 >= OutputLen ) 4470285612Sdelphij break ; 4471285612Sdelphij snprintf( sOutput + j, OutputLen - j, "<x%X>", 4472285612Sdelphij sInput[i] & 0xFF ) ; 4473285612Sdelphij } 4474285612Sdelphij j += n ; 4475285612Sdelphij } 4476285612Sdelphij 4477285612Sdelphij sOutput[min(j, (size_t)iOutputLen - 1)] = '\0' ; 4478285612Sdelphij 4479285612Sdelphij} 4480285612Sdelphij 4481285612Sdelphij/**************************************************************************************************/ 4482285612Sdelphij 4483106163Sroberto#else 4484106163Srobertoint refclock_jjy_bs ; 4485106163Sroberto#endif /* REFCLOCK */ 4486