File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / refclock_hopfser.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:37 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  *
    3:  * refclock_hopfser.c
    4:  * - clock driver for hopf serial boards (GPS or DCF77)
    5:  *
    6:  * Date: 30.03.2000 Revision: 01.10
    7:  *
    8:  * latest source and further information can be found at:
    9:  * http://www.ATLSoft.de/ntp
   10:  *
   11:  */
   12: 
   13: #ifdef HAVE_CONFIG_H
   14: # include "config.h"
   15: #endif
   16: 
   17: #if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
   18: 
   19: #include "ntpd.h"
   20: #include "ntp_io.h"
   21: #include "ntp_control.h"
   22: #include "ntp_refclock.h"
   23: #include "ntp_unixtime.h"
   24: #include "ntp_stdlib.h"
   25: 
   26: #if defined HAVE_SYS_MODEM_H
   27: # include <sys/modem.h>
   28: # ifndef __QNXNTO__
   29: #  define TIOCMSET MCSETA
   30: #  define TIOCMGET MCGETA
   31: #  define TIOCM_RTS MRTS
   32: # endif
   33: #endif
   34: 
   35: #ifdef HAVE_TERMIOS_H
   36: # ifdef TERMIOS_NEEDS__SVID3
   37: #  define _SVID3
   38: # endif
   39: # include <termios.h>
   40: # ifdef TERMIOS_NEEDS__SVID3
   41: #  undef _SVID3
   42: # endif
   43: #endif
   44: 
   45: #ifdef HAVE_SYS_IOCTL_H
   46: # include <sys/ioctl.h>
   47: #endif
   48: 
   49: #ifdef SYS_WINNT
   50: extern int async_write(int, const void *, unsigned int);
   51: #undef write
   52: #define write(fd, data, octets)	async_write(fd, data, octets)
   53: #endif
   54: 
   55: /*
   56:  * clock definitions
   57:  */
   58: #define	DESCRIPTION	"hopf Elektronik serial clock" /* Long name */
   59: #define	PRECISION	(-10)	/* precision assumed (about 1 ms) */
   60: #define	REFID		"hopf\0"	/* reference ID */
   61: /*
   62:  * I/O definitions
   63:  */
   64: #define	DEVICE		"/dev/hopfclock%d" 	/* device name and unit */
   65: #define	SPEED232	B9600		    	/* uart speed (9600 baud) */
   66: 
   67: 
   68: #define STX 0x02
   69: #define ETX 0x03
   70: #define CR  0x0c
   71: #define LF  0x0a
   72: 
   73: /* parse states */
   74: #define REC_QUEUE_EMPTY       0
   75: #define REC_QUEUE_FULL        1
   76: 
   77: #define	HOPF_OPMODE	0x0C	/* operation mode mask */
   78: #define HOPF_INVALID	0x00	/* no time code available */
   79: #define HOPF_INTERNAL	0x04	/* internal clock */
   80: #define HOPF_RADIO	0x08	/* radio clock */
   81: #define HOPF_RADIOHP	0x0C	/* high precision radio clock */
   82: 
   83: /*
   84:  * hopfclock unit control structure.
   85:  */
   86: struct hopfclock_unit {
   87: 	l_fp	laststamp;	/* last receive timestamp */
   88: 	short	unit;		/* NTP refclock unit number */
   89: 	u_long	polled;		/* flag to detect noreplies */
   90: 	char	leap_status;	/* leap second flag */
   91: 	int	rpt_next;
   92: };
   93: 
   94: /*
   95:  * Function prototypes
   96:  */
   97: 
   98: static	int	hopfserial_start	(int, struct peer *);
   99: static	void	hopfserial_shutdown	(int, struct peer *);
  100: static	void	hopfserial_receive	(struct recvbuf *);
  101: static	void	hopfserial_poll		(int, struct peer *);
  102: /* static  void hopfserial_io		(struct recvbuf *); */
  103: /*
  104:  * Transfer vector
  105:  */
  106: struct refclock refclock_hopfser = {
  107: 	hopfserial_start,	/* start up driver */
  108: 	hopfserial_shutdown,	/* shut down driver */
  109: 	hopfserial_poll,	/* transmit poll message */
  110: 	noentry,		/* not used  */
  111: 	noentry,		/* initialize driver (not used) */
  112: 	noentry,		/* not used */
  113: 	NOFLAGS			/* not used */
  114: };
  115: 
  116: /*
  117:  * hopfserial_start - open the devices and initialize data for processing
  118:  */
  119: static int
  120: hopfserial_start (
  121: 	int unit,
  122: 	struct peer *peer
  123: 	)
  124: {
  125: 	register struct hopfclock_unit *up;
  126: 	struct refclockproc *pp;
  127: 	int fd;
  128: 	char gpsdev[20];
  129: 
  130: 	snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
  131: 
  132: 	/* LDISC_STD, LDISC_RAW
  133: 	 * Open serial port. Use CLK line discipline, if available.
  134: 	 */
  135: 	fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
  136: 	if (fd <= 0) {
  137: #ifdef DEBUG
  138: 		printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
  139: #endif
  140: 		return 0;
  141: 	}
  142: 
  143: 	msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
  144: 		gpsdev);
  145: 
  146: 	/*
  147: 	 * Allocate and initialize unit structure
  148: 	 */
  149: 	up = emalloc(sizeof(*up));
  150: 	memset(up, 0, sizeof(*up));
  151: 	pp = peer->procptr;
  152: 	pp->unitptr = (caddr_t)up;
  153: 	pp->io.clock_recv = hopfserial_receive;
  154: 	pp->io.srcclock = (caddr_t)peer;
  155: 	pp->io.datalen = 0;
  156: 	pp->io.fd = fd;
  157: 	if (!io_addclock(&pp->io)) {
  158: #ifdef DEBUG
  159: 		printf("hopfSerialClock(%d) io_addclock\n", unit);
  160: #endif
  161: 		close(fd);
  162: 		pp->io.fd = -1;
  163: 		free(up);
  164: 		pp->unitptr = NULL;
  165: 		return (0);
  166: 	}
  167: 
  168: 	/*
  169: 	 * Initialize miscellaneous variables
  170: 	 */
  171: 	pp->clockdesc = DESCRIPTION;
  172: 	peer->precision = PRECISION;
  173: 	peer->burst = NSTAGE;
  174: 	memcpy((char *)&pp->refid, REFID, 4);
  175: 
  176: 	up->leap_status = 0;
  177: 	up->unit = (short) unit;
  178: 
  179: 	return (1);
  180: }
  181: 
  182: 
  183: /*
  184:  * hopfserial_shutdown - shut down the clock
  185:  */
  186: static void
  187: hopfserial_shutdown (
  188: 	int unit,
  189: 	struct peer *peer
  190: 	)
  191: {
  192: 	register struct hopfclock_unit *up;
  193: 	struct refclockproc *pp;
  194: 
  195: 	pp = peer->procptr;
  196: 	up = (struct hopfclock_unit *)pp->unitptr;
  197: 
  198: 	if (-1 != pp->io.fd)
  199: 		io_closeclock(&pp->io);
  200: 	if (NULL != up)
  201: 		free(up);
  202: }
  203: 
  204: 
  205: 
  206: /*
  207:  * hopfserial_receive - receive data from the serial interface
  208:  */
  209: 
  210: static void
  211: hopfserial_receive (
  212: 	struct recvbuf *rbufp
  213: 	)
  214: {
  215: 	struct hopfclock_unit *up;
  216: 	struct refclockproc *pp;
  217: 	struct peer *peer;
  218: 
  219: 	int		synch;	/* synchhronization indicator */
  220: 	int		DoW;	/* Dow */
  221: 
  222: 	int	day, month;	/* ddd conversion */
  223: 
  224: 	/*
  225: 	 * Initialize pointers and read the timecode and timestamp.
  226: 	 */
  227: 	peer = (struct peer *)rbufp->recv_srcclock;
  228: 	pp = peer->procptr;
  229: 	up = (struct hopfclock_unit *)pp->unitptr;
  230: 
  231: 	if (up->rpt_next == 0 )
  232: 		return;
  233: 
  234: 
  235: 	up->rpt_next = 0; /* wait until next poll interval occur */
  236: 
  237: 	pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
  238: 
  239: 	if (pp->lencode  == 0)
  240: 		return;
  241: 
  242: 	sscanf(pp->a_lastcode,
  243: #if 1
  244: 	       "%1x%1x%2d%2d%2d%2d%2d%2d",   /* ...cr,lf */
  245: #else
  246: 	       "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
  247: #endif
  248: 	       &synch,
  249: 	       &DoW,
  250: 	       &pp->hour,
  251: 	       &pp->minute,
  252: 	       &pp->second,
  253: 	       &day,
  254: 	       &month,
  255: 	       &pp->year);
  256: 
  257: 
  258: 	/*
  259: 	  Validate received values at least enough to prevent internal
  260: 	  array-bounds problems, etc.
  261: 	*/
  262: 	if((pp->hour < 0) || (pp->hour > 23) ||
  263: 	   (pp->minute < 0) || (pp->minute > 59) ||
  264: 	   (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
  265: 	   (day < 1) || (day > 31) ||
  266: 	   (month < 1) || (month > 12) ||
  267: 	   (pp->year < 0) || (pp->year > 99)) {
  268: 		/* Data out of range. */
  269: 		refclock_report(peer, CEVNT_BADREPLY);
  270: 		return;
  271: 	}
  272: 	/*
  273: 	  some preparations
  274: 	*/
  275: 	pp->day    = ymd2yd(pp->year,month,day);
  276: 	pp->leap=0;
  277: 
  278: 	/* Year-2000 check! */
  279: 	/* wrap 2-digit date into 4-digit */
  280: 
  281: 	if(pp->year < YEAR_PIVOT) { pp->year += 100; }		/* < 98 */
  282: 	pp->year += 1900;
  283: 
  284: 	/* preparation for timecode ntpq rl command ! */
  285: 
  286: #if 0
  287: 	snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
  288: 		 "STATUS: %1X%1X, DATE: %02d.%02d.%04d  TIME: %02d:%02d:%02d",
  289: 		 synch,
  290: 		 DoW,
  291: 		 day,
  292: 		 month,
  293: 		 pp->year,
  294: 		 pp->hour,
  295: 		 pp->minute,
  296: 		 pp->second);
  297: 
  298: 	pp->lencode = strlen(pp->a_lastcode);
  299: 	if ((synch && 0xc) == 0 ){  /* time ok? */
  300: 		refclock_report(peer, CEVNT_BADTIME);
  301: 		pp->leap = LEAP_NOTINSYNC;
  302: 		return;
  303: 	}
  304: #endif
  305: 	/*
  306: 	 * If clock has no valid status then report error and exit
  307: 	 */
  308: 	if ((synch & HOPF_OPMODE) == HOPF_INVALID ){  /* time ok? */
  309: 		refclock_report(peer, CEVNT_BADTIME);
  310: 		pp->leap = LEAP_NOTINSYNC;
  311: 		return;
  312: 	}
  313: 
  314: 	/*
  315: 	 * Test if time is running on internal quarz
  316: 	 * if CLK_FLAG1 is set, sychronize even if no radio operation
  317: 	 */
  318: 
  319: 	if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
  320: 		if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
  321: 			refclock_report(peer, CEVNT_BADTIME);
  322: 			pp->leap = LEAP_NOTINSYNC;
  323: 			return;
  324: 		}
  325: 	}
  326: 
  327: 
  328: 	if (!refclock_process(pp)) {
  329: 		refclock_report(peer, CEVNT_BADTIME);
  330: 		return;
  331: 	}
  332: 	pp->lastref = pp->lastrec;
  333: 	refclock_receive(peer);
  334: 
  335: #if 0
  336: 	msyslog(LOG_ERR, " D:%x  D:%d D:%d",synch,pp->minute,pp->second);
  337: #endif
  338: 
  339: 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
  340: 
  341: 	return;
  342: }
  343: 
  344: 
  345: /*
  346:  * hopfserial_poll - called by the transmit procedure
  347:  *
  348:  */
  349: static void
  350: hopfserial_poll (
  351: 	int unit,
  352: 	struct peer *peer
  353: 	)
  354: {
  355: 	register struct hopfclock_unit *up;
  356: 	struct refclockproc *pp;
  357: 	pp = peer->procptr;
  358: 
  359: 	up = (struct hopfclock_unit *)pp->unitptr;
  360: 
  361: 	pp->polls++;
  362: 	up->rpt_next = 1;
  363: 
  364: #if 0
  365: 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
  366: #endif
  367: 
  368: 	return;
  369: }
  370: 
  371: #else
  372: int refclock_hopfser_bs;
  373: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>