[ntp:questions] Problems with NMEA refclocks, Ublox6 GPS, on WinXP with 4.2.7p21 4

Dave Hart davehart at gmail.com
Tue Sep 27 16:07:33 UTC 2011


On Tue, Sep 27, 2011 at 11:03 UTC, Darren wrote:
> I tried asking about my problems on the IRC channel #ntp last night but got
> no response so I thought I'd try the questions list.

Sorry I missed you there.  On the other hand, now there's a
web-searchable record of your troubles that might help someone else in
the future.

> I'm trying to use a pure NMEA refclock (no PPS) on Win XP but I'm not having
> any joy. I've been trying with 4.2.7p214 and tested briefly with 4.2.6p4 to
> see if it was any better and it didn't seem to be.
>
> I seem to have two problems.  One is specifically related to the particular
> GPS device I need to use, and the other seems to be common to the other NMEA
> sources I've tried.
>
> I'm specifically trying to get a Ublox6 GPS to talk to ntpd via a USB-UART
> at 9600 baud, but the issues with the Ublox6 seem to be more severe than
> with the other NMEA sources that I've tried.  With the Ublox6, in
> _open_osfhandle(), isdev == FILE_TYPE_UNKNOWN and the function returns -1,
> causing nmea_start() to call nmead_open(), which I guess it shouldn't. The
> call to nmead_open() also returns -1, causing nmea_shutdown() to be invoked,
> so then its game over for that refclock.  If I hack isdev to equal
> FILE_TYPE_CHAR, then the results obtained with the Ublox6 are the same as
> those described below for other NMEA sources.

That's a nasty little problem.  _open_osfhandle() is called by
ports/winnt/libntp/termios.c's refclock_open() to map a Win32 HANDLE
for the serial port to a MS C runtime file descriptor.  No operations
are carried out using that descriptor by the Windows serial code in
ntpd, rather, the original Win32 HANDLE is retrieved using
_get_osfhandle(fd).  Nonetheless, the mapping to a file descriptor is
important to the way the Windows port of ntpd minimizes changes to
POSIX reference clock source code.

I'm still using Visual C++ 2008 Express (no longer available for
public download, AFAICS) though I also have Visual C++ 2010 Express
installed, and fortunately, the latter includes a copy of most of the
C runtime code, including vc\crt\src\osfinfo.c implementing
_open_osfhandle().  Assuming the code didn't change between those
releases, note what it does:

        /* find out what type of file (file/device/pipe) */

        isdev = GetFileType((HANDLE)osfhandle);
        if (isdev == FILE_TYPE_UNKNOWN) {
            /* OS error */
            _dosmaperr( GetLastError() );   /* map error */
            return -1;
        }

        /* is isdev value to set flags */
        if (isdev == FILE_TYPE_CHAR)
            fileflags |= FDEV;
        else if (isdev == FILE_TYPE_PIPE)
            fileflags |= FPIPE;

So it's calling the Win32 API GetFileType() to distinguish regular
(disk) files, which get no special fileflags, from devices and pipes
which do.  GetFileType is documented here:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364960(v=vs.85).aspx
or
http://preview.tinyurl.com/3rswxve

The GetFileType documentation points out that a return value of
FILE_TYPE_UNKNOWN (== 0) means either the function failed, or the type
of the handle is unknown, and one must call GetLastError() to know
which.  I suggest you debug the problem again and determine what
GetLastError() is returning in this path.  My guess is it's returning
0 (no error) indicating the driver handling the USB-connected UART is
failing to set the right bits to indicate it's a communications device
during the open operation.  If GetLastError() is returning an error
value, something else is going wrong.  I'd really like to know whether
GetFileType() is reporting an error or a legitimate FILE_TYPE_UNKNOWN.

Assuming a driver problem, I understand there are relatively few
USB-to-UART bridging chips in the market, with something called the
pl2003 (IIRC) found in most USB-connected GPS pucks.  With enough
spelunking, perhaps you can arrange to use a better Windows driver
compatible with your USB-UART hardware to work around this problem.

I do question my guess, though, as I'd expect failure to report
FILE_TYPE_CHAR would also prevent other terminal apps from using the
device, as for example setting the serial port rate and configuration
presumably fails on devices that do not present as a communications
device.

> I've also tried using a Kenwood D72 transceiver's embedded GPS Rx, also via
> its embedded USB-UART, and a GPS Emulator (that's popular with the people at
> the diy-drones forum) interfaced with a com0com virtual serial port
> connection. With the D72 and the emulator on Windows XP, nmea_start() seems
> to succeed, but nmea_receive() never seems to be invoked.

You can't get a break, can you?  I'm curious what role the GPS
emulator is playing here.  Why not use the D72 directly?  Does putty
or another terminal program show you the NMEA transmissions each
second when opening the same COM port as ntpd is attempting?  The
serial reading code in the Windows ntpd port waits for the driver to
indicate the "event character" CR was seen, then it issues a
nonblocking read for all buffered bytes, simulating a POSIX
line-oriented serial driver.  nmea_receive() should be called twice
for each line, first with a nonzero length and the sentence (minus
linebreak), then with a zero length, again emulating a POSIX line
discipline which considers the CR to terminate one line, and the
following LF terminating an empty line.

I understand you saw the same problem with the Ublox part when you
hacked around the _open_osfhandle() failure in the debugger.  That
seems like a an important hint, but I'm still baffled about what might
be amiss.  There are plenty of places you can set breakpoints or add
DPRINTF() or msyslog() calls to help you narrow down the failure,
though.

Good luck,
Dave Hart



More information about the questions mailing list