📄 refclock_oncore.c
字号:
static u_char oncore_cmd_Az[] = { 'A', 'z', 0, 0, 0, 0 }; /* 6/8UT/12 1PPS Cable Delay: set */static u_char oncore_cmd_Azx[] = { 'A', 'z', 0xff, 0xff, 0xff, 0xff }; /* 6/8UT/12 1PPS Cable Delay: Read */static u_char oncore_cmd_Ba0[] = { 'B', 'a', 0 }; /* 6 Position/Data/Status: off */static u_char oncore_cmd_Ba[] = { 'B', 'a', 1 }; /* 6 Position/Data/Status: on */static u_char oncore_cmd_Bb[] = { 'B', 'b', 1 }; /* 6/8/12 Visible Satellites */static u_char oncore_cmd_Bd[] = { 'B', 'd', 1 }; /* 6/8/12? Almanac Status Msg. */static u_char oncore_cmd_Be[] = { 'B', 'e', 1 }; /* 6/8/12 Request Almanac Data */static u_char oncore_cmd_Bj[] = { 'B', 'j', 0 }; /* 6/8 Leap Second Pending */static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg off, traim on */static u_char oncore_cmd_Bn[] = { 'B', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg on, traim on */static u_char oncore_cmd_Bnx[] = { 'B', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg off, traim off */static u_char oncore_cmd_Ca[] = { 'C', 'a' }; /* 6 Self Test */static u_char oncore_cmd_Cf[] = { 'C', 'f' }; /* 6/8/12 Set to Defaults */static u_char oncore_cmd_Cg[] = { 'C', 'g', 1 }; /* VP Posn Fix/Idle Mode */static u_char oncore_cmd_Cj[] = { 'C', 'j' }; /* 6/8/12 Receiver ID */static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 }; /* 8 Position/Data/Status: off */static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 }; /* 8 Position/Data/Status: on */static u_char oncore_cmd_Ek[] = { 'E', 'k', 0 }; /* just turn off */ /* 8 Posn/Status/Data - extension */static u_char oncore_cmd_En0[] = { 'E', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg off, traim on */static u_char oncore_cmd_En[] = { 'E', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg on, traim on */static u_char oncore_cmd_Enx[] = { 'E', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg off, traim off */static u_char oncore_cmd_Fa[] = { 'F', 'a' }; /* 8 Self Test */static u_char oncore_cmd_Ga[] = { 'G', 'a', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 }; /* 12 Position Set */static u_char oncore_cmd_Gax[] = { 'G', 'a', 0xff, 0xff, 0xff, 0xff, /* 12 Position Set: Read */ 0xff, 0xff, 0xff, 0xff, /* */ 0xff, 0xff, 0xff, 0xff, 0xff }; /* */static u_char oncore_cmd_Gb[] = { 'G', 'b', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 12 set Date/Time */static u_char oncore_cmd_Gc[] = { 'G', 'c', 1 }; /* 12 PPS Control: On Cont */static u_char oncore_cmd_Gd0[] = { 'G', 'd', 0 }; /* 12 Position Control: 3D (no hold) */static u_char oncore_cmd_Gd1[] = { 'G', 'd', 1 }; /* 12 Position Control: 0D (3D hold) */static u_char oncore_cmd_Gd2[] = { 'G', 'd', 2 }; /* 12 Position Control: 2D (Alt Hold) */static u_char oncore_cmd_Gd3[] = { 'G', 'd', 3 }; /* 12 Position Coltrol: Start Site Survey */static u_char oncore_cmd_Ge0[] = { 'G', 'e', 0 }; /* M12+T TRAIM: off */static u_char oncore_cmd_Ge[] = { 'G', 'e', 1 }; /* M12+T TRAIM: on */static u_char oncore_cmd_Gj[] = { 'G', 'j' }; /* 8?/12 Leap Second Pending */static u_char oncore_cmd_Ha0[] = { 'H', 'a', 0 }; /* 12 Position/Data/Status: off */static u_char oncore_cmd_Ha[] = { 'H', 'a', 1 }; /* 12 Position/Data/Status: on */static u_char oncore_cmd_Hn0[] = { 'H', 'n', 0 }; /* 12 TRAIM Status: off */static u_char oncore_cmd_Hn[] = { 'H', 'n', 1 }; /* 12 TRAIM Status: on */static u_char oncore_cmd_Ia[] = { 'I', 'a' }; /* 12 Self Test *//* it appears that as of 1997/1998, the UT had As,At, but not Au,Av * the GT had Au,Av, but not As,At * This was as of v2.0 of both firmware sets. possibly 1.3 for UT. * Bj in UT at v1.3 * dont see Bd in UT/GT thru 1999 * Gj in UT as of 3.0, 1999 , Bj as of 1.3 */static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly", "Aug", "Sep", "Oct", "Nov", "Dec" };#define DEVICE1 "/dev/oncore.serial.%d" /* name of serial device */#define DEVICE2 "/dev/oncore.pps.%d" /* name of pps device */#define SPEED B9600 /* Oncore Binary speed (9600 bps) *//* * Assemble and disassemble 32bit signed quantities from a buffer. * */ /* to buffer, int w, u_char *buf */#define w32_buf(buf,w) { u_int i_tmp; \ i_tmp = (w<0) ? (~(-w)+1) : (w); \ (buf)[0] = (i_tmp >> 24) & 0xff; \ (buf)[1] = (i_tmp >> 16) & 0xff; \ (buf)[2] = (i_tmp >> 8) & 0xff; \ (buf)[3] = (i_tmp ) & 0xff; \ }#define w32(buf) (((buf)[0]&0xff) << 24 | \ ((buf)[1]&0xff) << 16 | \ ((buf)[2]&0xff) << 8 | \ ((buf)[3]&0xff) ) /* from buffer, char *buf, result to an int */#define buf_w32(buf) (((buf)[0]&0200) ? (-(~w32(buf)+1)) : w32(buf))/* * oncore_start - initialize data for processing */static intoncore_start( int unit, struct peer *peer ){ register struct instance *instance; struct refclockproc *pp; int fd1, fd2; char device1[30], device2[30]; const char *cp; struct stat stat1, stat2; /* OPEN DEVICES */ /* opening different devices for fd1 and fd2 presents no problems */ /* opening the SAME device twice, seems to be OS dependent. (a) on Linux (no streams) no problem (b) on SunOS (and possibly Solaris, untested), (streams) never see the line discipline. Since things ALWAYS work if we only open the device once, we check to see if the two devices are in fact the same, then proceed to do one open or two. */ (void)sprintf(device1, DEVICE1, unit); (void)sprintf(device2, DEVICE2, unit); if (stat(device1, &stat1)) { perror("ONCORE: stat fd1"); exit(1); } if (stat(device2, &stat2)) { perror("ONCORE: stat fd2"); exit(1); } /* create instance structure for this unit */ if (!(instance = (struct instance *) malloc(sizeof *instance))) { perror("malloc"); return (0); } memset((char *) instance, 0, sizeof *instance); if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW))) { perror("ONCORE: fd1"); exit(1); } if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) /* same device here */ fd2 = fd1; else { /* different devices here */ if ((fd2=open(device2, O_RDWR)) < 0) { perror("ONCORE: fd2"); exit(1); } } /* initialize miscellaneous variables */ pp = peer->procptr; pp->unitptr = (caddr_t) instance; instance->pp = pp; instance->unit = unit; instance->peer = peer; instance->assert = 1; instance->once = 1; cp = "ONCORE DRIVER -- CONFIGURING"; record_clock_stats(&(instance->peer->srcadr), cp); instance->o_state = ONCORE_NO_IDEA; cp = "state = ONCORE_NO_IDEA"; record_clock_stats(&(instance->peer->srcadr), cp); instance->ttyfd = fd1; instance->ppsfd = fd2; instance->Bj_day = -1; instance->traim = -1; instance->traim_in = -1; instance->chan_in = -1; instance->model = ONCORE_UNKNOWN; instance->mode = MODE_UNKNOWN; instance->site_survey = ONCORE_SS_UNKNOWN; instance->Ag = 0xff; /* Satellite mask angle, unset by user */ instance->ant_state = ONCORE_ANTENNA_UNKNOWN; peer->precision = -26; peer->minpoll = 4; peer->maxpoll = 4; pp->clockdesc = "Motorola Oncore GPS Receiver"; memcpy((char *)&pp->refid, "GPS\0", (size_t) 4); /* go read any input data in /etc/ntp.oncoreX or /etc/ntp/oncore.X */ oncore_read_config(instance); if (time_pps_create(fd2, &instance->pps_h) < 0) { perror("time_pps_create: PPSAPI probably not in kernel"); record_clock_stats(&(instance->peer->srcadr), "PPSAPI not found in kernel"); return(0); } if (!oncore_ppsapi(instance)) return(0); pp->io.clock_recv = oncore_receive; pp->io.srcclock = (caddr_t)peer; pp->io.datalen = 0; pp->io.fd = fd1; if (!io_addclock(&pp->io)) { perror("io_addclock"); (void) close(fd1); free(instance); return (0); }#ifdef ONCORE_SHMEM_STATUS /* * Before starting ONCORE, lets setup SHMEM * This will include merging an old SHMEM into the new one if * an old one is found. */ oncore_init_shmem(instance);#endif /* * This will return the Model of the Oncore receiver. * and start the Initialization loop in oncore_msg_Cj. */ instance->o_state = ONCORE_CHECK_ID; cp = "state = ONCORE_CHECK_ID"; record_clock_stats(&(instance->peer->srcadr), cp); instance->timeout = 4; oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj)); instance->pollcnt = 2; return (1);}/* * oncore_shutdown - shut down the clock */static voidoncore_shutdown( int unit, struct peer *peer ){ register struct instance *instance; struct refclockproc *pp; pp = peer->procptr; instance = (struct instance *) pp->unitptr; io_closeclock(&pp->io); close(instance->ttyfd); close(instance->ppsfd); if (instance->shmemfd) close(instance->shmemfd); free(instance);}/* * oncore_poll - called by the transmit procedure */static voidoncore_poll( int unit, struct peer *peer ){ struct instance *instance; instance = (struct instance *) peer->procptr->unitptr; if (instance->timeout) { char *cp; instance->timeout--; if (instance->timeout == 0) { cp = "Oncore: No response from @@Cj, shutting down driver"; record_clock_stats(&(instance->peer->srcadr), cp); oncore_shutdown(unit, peer); } else { oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj)); cp = "Oncore: Resend @@Cj"; record_clock_stats(&(instance->peer->srcadr), cp); } return; } if (!instance->pollcnt) refclock_report(peer, CEVNT_TIMEOUT); else instance->pollcnt--; peer->procptr->polls++; instance->polled = 1;}/* * Initialize PPSAPI */static intoncore_ppsapi( struct instance *instance ){ int cap, mode, mode1; char *cp, Msg[160]; if (time_pps_getcap(instance->pps_h, &cap) < 0) { msyslog(LOG_ERR, "time_pps_getcap failed: %m"); return (0); } if (time_pps_getparams(instance->pps_h, &instance->pps_p) < 0) { msyslog(LOG_ERR, "time_pps_getparams failed: %m"); return (0); } /* nb. only turn things on, if someone else has turned something * on before we get here, leave it alone! */ if (instance->assert) { cp = "Assert."; mode = PPS_CAPTUREASSERT; mode1 = PPS_OFFSETASSERT; } else { cp = "Clear."; mode = PPS_CAPTURECLEAR; mode1 = PPS_OFFSETCLEAR; } sprintf(Msg, "Initializing timeing to %s.", cp); record_clock_stats(&(instance->peer->srcadr), Msg); if (!(mode & cap)) { sprintf(Msg, "Can't set timeing to %s, exiting...", cp); record_clock_stats(&(instance->peer->srcadr), Msg); return(0); } if (!(mode1 & cap)) { sprintf(Msg, "Can't set PPS_%sCLEAR, this will increase jitter.", cp); record_clock_stats(&(instance->peer->srcadr), Msg); mode1 = 0; } /* only set what is legal */ instance->pps_p.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap; if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) { perror("time_pps_setparams"); exit(1); } /* If HARDPPS is on, we tell kernel */ if (instance->hardpps) { int i; record_clock_stats(&(instance->peer->srcadr), "HARDPPS Set."); if (instance->assert) i = PPS_CAPTUREASSERT; else i = PPS_CAPTURECLEAR; /* we know that 'i' is legal from above */ if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i, PPS_TSFMT_TSPEC) < 0) { msyslog(LOG_ERR, "time_pps_kcbind failed: %m"); record_clock_stats(&(instance->peer->srcadr), "HARDPPS failed, abort..."); return (0); } pps_enable = 1; } return(1);}#ifdef ONCORE_SHMEM_STATUSstatic voidoncore_init_shmem( struct instance *instance ){ int i, l, n, fd, shmem_old_size, n1; char *buf, Msg[160]; u_char *cp, *cp1, *shmem_old; struct msg_desc *mp; struct stat sbuf; size_t shmem_length; /* * The first thing we do is see if there is an instance->shmem_fname file (still) * out there from a previous run. If so, we copy it in and use it to initialize * shmem (so we won't lose our almanac if we need it). */ shmem_old = 0; if ((fd = open(instance->shmem_fname, O_RDONLY)) < 0) perror("LOAD:SHMEM"); else { fstat(fd, &sbuf); shmem_old_size = sbuf.st_size; shmem_old = (u_char *) malloc((unsigned) sbuf.st_size); if (shmem_old == NULL) { perror("malloc"); close(fd); return; } read(fd, shmem_old, shmem_old_size); close(fd); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -