191094Sdes/* $NetBSD: clk_sel240x.c,v 1.6 2020/05/25 20:47:25 christos Exp $ */ 292289Sdes 391094Sdes////////////////////////////////////////////////////////////////////////////// 491094Sdes// Copyright (c) 2009,2012 - 591094Sdes// Schweitzer Engineering Laboratories, Inc. <opensource@selinc.com> 699158Sdes////////////////////////////////////////////////////////////////////////////// 799158Sdes 899158Sdes// Need to have _XOPEN_SOURCE defined for time.h to give the 991094Sdes// correct strptime signature. As per feature_test_macros(7), 1091094Sdes// define this before including any header files. 1191094Sdes 1291094Sdes// #ifndef _XOPEN_SOURCE 1391094Sdes// #define _XOPEN_SOURCE 1491094Sdes// #endif 1591094Sdes 1691094Sdes#ifdef HAVE_CONFIG_H 1791094Sdes# include <config.h> 1891094Sdes#endif 1991094Sdes 2091094Sdes#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X) 2191094Sdes 2291094Sdes#include "ntp_syslog.h" 2391094Sdes#include "ntp_types.h" 2491094Sdes#include "ntp_fp.h" 2591094Sdes#include "ntp_unixtime.h" 2691094Sdes#include "ntp_calendar.h" 2791094Sdes#include "ntp_machine.h" 2891094Sdes#include "ntp_stdlib.h" 2991094Sdes 3091094Sdes#include "parse.h" 3191094Sdes 3291094Sdes#ifndef PARSESTREAM 3391094Sdes# include <stdio.h> 3499158Sdes#else 3591094Sdes# include "sys/parsestreams.h" 3691094Sdes#endif 3791094Sdes 3891094Sdes#include <time.h> 3991100Sdes 4091100Sdes////////////////////////////////////////////////////////////////////////////// 4191100Sdes// The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n' 4291100Sdes// where q = ' ' locked 4391100Sdes// '.' <1 us 4491100Sdes// '*' <10 us 4591100Sdes// '#' <100 us 4691094Sdes// '?' >100 us 4791094Sdes// 4891094Sdes// Based on this we need to recored the stime when we receive the <SOH> 4991094Sdes// character and end it when we see the \n. 5091094Sdes// 5191094Sdes// The q or quality character indicates satellite lock and sync. For the 5291094Sdes// purposes of NTP we are going to call it valid when we receive anything but 5391094Sdes// a '?'. But we are only going to call it synced when we receive a ' ' 5491094Sdes////////////////////////////////////////////////////////////////////////////// 5591094Sdes 5691094Sdesstatic parse_inp_fnc_t inp_sel240x; 5791094Sdesstatic parse_cvt_fnc_t cvt_sel240x; 5891100Sdes 5991100Sdes// Parse clock format structure describing the message above 6091100Sdesstatic struct format sel240x_fmt = 6191100Sdes{ { { 6, 3 }, 62 { 0, 0 }, 63 { 1, 4 }, 64 { 10, 2 }, 65 { 13, 2 }, 66 { 16, 2 }, 67 { 0, 0 }, 68 { 0, 0 }, 69 { 0, 0 }, 70 { 0, 0 }, 71 { 0, 0 }, 72 { 0, 0 } 73 }, 74 (const unsigned char *)"\x01 : : : : \x0d\x0a", 75 0 76}; 77 78// Structure desctibing the parser 79clockformat_t clock_sel240x = 80{ 81 inp_sel240x, 82 cvt_sel240x, 83 pps_one, 84 (void*)&sel240x_fmt, 85 "SEL B8", 86 25, 87 0 88}; 89 90////////////////////////////////////////////////////////////////////////////// 91static unsigned long 92inp_sel240x( parse_t *parseio, 93 char ch, 94 timestamp_t *tstamp 95 ) 96{ 97 unsigned long rc; 98 99 parseprintf( DD_PARSE, 100 ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch)); 101 102 switch( ch ) 103 { 104 case '\x01': 105 parseio->parse_index = 1; 106 parseio->parse_data[0] = ch; 107 parseio->parse_dtime.parse_stime = *tstamp; 108 rc = PARSE_INP_SKIP; 109 break; 110 case '\n': 111 if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP ) 112 { 113 rc = parse_end( parseio ); 114 } 115 break; 116 default: 117 rc = parse_addchar( parseio, ch ); 118 } 119 120 return rc; 121} 122 123////////////////////////////////////////////////////////////////////////////// 124static unsigned long 125cvt_sel240x( unsigned char *buffer, 126 int size, 127 struct format *format, 128 clocktime_t *clock_time, 129 void *local 130 ) 131{ 132 unsigned long rc = CVT_NONE; 133 134 if( Strok(buffer, format->fixed_string) ) 135 { 136 struct tm ptime; 137 buffer++; 138 buffer = (unsigned char *) strptime( 139 (const char *)buffer, "%Y:%j:%H:%M:%S", &ptime ); 140 if( *(buffer+1) != '\x0d' ) 141 { 142 rc = CVT_FAIL | CVT_BADFMT; 143 } 144 else 145 { 146 clock_time->day = ptime.tm_mday; 147 clock_time->month = ptime.tm_mon + 1; 148 clock_time->year = ptime.tm_year + 1900; 149 clock_time->hour = ptime.tm_hour; 150 clock_time->minute = ptime.tm_min; 151 clock_time->second = ptime.tm_sec; 152 clock_time->usecond = 0; 153 clock_time->utcoffset = 0; 154 clock_time->flags = PARSEB_UTC; 155 156 if( *buffer == '?' ) 157 { 158 clock_time->flags |= PARSEB_POWERUP; 159 } 160 else if( *buffer != ' ' ) 161 { 162 clock_time->flags |= PARSEB_NOSYNC; 163 } 164 165 rc = CVT_OK; 166 } 167 } 168 169 return rc; 170} 171 172#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 173int clk_sel240x_bs; 174#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ 175