[LinuxPPS] refclock_nmea patch

Udo van den Heuvel udovdh at xs4all.nl
Tue Oct 23 17:41:07 CEST 2007


Rodolfo Giometti wrote:
> On Tue, Oct 23, 2007 at 05:54:43AM +0200, Udo van den Heuvel wrote:
>> You mean NMEA when you say 'GPS data source'?
>> I think both, looking at the code. (where the PPS API interface is started)
> 
> But when you talk about /dev/gps0 you point __only__ the GPS data
> source, while you talk about /dev/pps0 you point __only__ the PPS data
> source. NMEA is represented by both /dev/gps0 __and__ /dev/pps0.

Yes, but now what if we have a device with one /dev/bla giving NMEA and
another /dev/duh giving PPS?
How is the first /dev/bla passed on to ntpd?
I don't get this yet.

In my own situation we have NMEA and PPS on teh same RS232 port.
I then expect the first link that I apss to LinuxPPS to be used, which
isn't.

>>> The former is correct beacuse /dev/gps0 is _not_ a PPS source, it's a
>>> serial line (points to /dev/ttyS0), the latter I don't know. :)
>> We open a fd on a device, do time_pps_create and when it fails, we open
>> the fd on another device, do another time_pps_create...
>> So the fd is not saved.
>> So how can ntpd use the first device for NMEA and the second for PPS?
> 
> I don't know NMEA code but it seems to me you are working inside a
> function, 

Yes.

> is the fd passed to it? 

No, it opens a fd on a com port at the start of the function.

> If not you have to save fd
> somewhere, maybe in up->fd?

So that is the place for the NMEA source?
And the return(nmea_ppsapi(peer, 0, 0)); is for the PPS?

>> Maybe this can help:
>> When is the /dev entry (pps0) created?
>> Based on what input?
> 
> If you have udev when the pps device is created, otherwise you have to
> create it by yourself by using mknod.

It was there, so udev works I guess.
How is decided what port is to be created?
I once had a /dev/gps0 and /dev/pps0 pointing to /dev/ttyS0.
/dev/pps0 was replaced by the new device entry.
Why?

> I don't know NMEA code but maybe here you are overriding the GPS data
> source file descriptor... if so you should use different variable
> (pps_fd?).
> 
> Can you please post the whole function you are modifying so I can
> understand if the fd should be renamed or not?

/*
 * nmea_start - open the GPS devices and initialize data for processing
 */
static int
nmea_start(
        int unit,
        struct peer *peer
        )
{
        register struct nmeaunit *up;
        struct refclockproc *pp;
        int fd;
        char device[20];

        /*
         * Open serial port. Use CLK line discipline, if available.
         */
        (void)sprintf(device, DEVICE, unit);

        fd = refclock_open(device, SPEED232, LDISC_CLK);
        if (fd <= 0) {
#ifdef HAVE_READLINK
(nmead stuff cut)
#endif
        }

        /*
         * Allocate and initialize unit structure
         */
        up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));
        if (up == NULL) {
                (void) close(fd);
                return (0);
        }
        memset((char *)up, 0, sizeof(struct nmeaunit));
        pp = peer->procptr;
        pp->io.clock_recv = nmea_receive;
        pp->io.srcclock = (caddr_t)peer;
        pp->io.datalen = 0;
        pp->io.fd = fd;
        if (!io_addclock(&pp->io)) {
                (void) close(fd);
                free(up);
                return (0);
        }
        pp->unitptr = (caddr_t)up;

        /*
         * Initialize miscellaneous variables
         */
        peer->precision = PRECISION;
        pp->clockdesc = DESCRIPTION;
        memcpy((char *)&pp->refid, REFID, 4);
        up->pollcnt = 2;
        gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);

#ifdef HAVE_PPSAPI
        /*
         * Start the PPSAPI interface if it is there. Default to use
         * the assert edge and do not enable the kernel hardpps.
         */
        if (time_pps_create(fd, &up->handle) < 0) {
                /* Try the alternate PPS device */
                (void) sprintf(device, DEVICEPPS, unit);
                msyslog(LOG_ERR, "refclock_nmea: try alternate PPS
device \"%s\"", device);
                fd = open(device, O_RDWR);
                if (fd < 0)
                        goto pps_error;
                if (time_pps_create(fd, &up->handle) < 0)
                        goto pps_error;
        }
        else (void) sprintf(device, DEVICE, unit); /* just rebuild
device's name */
        msyslog(LOG_INFO, "refclock_nmea: found PPS source \"%s\"", device);
        return(nmea_ppsapi(peer, 0, 0));
#else
        return (1);
#endif /* HAVE_PPSAPI */


Here it is.
I hope we can fix this issue and do some testing and send it to teh ntpd
folks this weekend?

Udo



More information about the LinuxPPS mailing list