Browse Source

Imported Upstream version 2.37

master
Bernd Zeimetz 12 years ago
parent
commit
925677ca54
100 changed files with 78252 additions and 0 deletions
  1. +9
    -0
      AUTHORS
  2. +32
    -0
      COPYING
  3. +147
    -0
      INSTALL
  4. +466
    -0
      Makefile.am
  5. +1748
    -0
      Makefile.in
  6. +123
    -0
      README
  7. +331
    -0
      TODO
  8. +581
    -0
      Tachometer.c
  9. +49
    -0
      Tachometer.h
  10. +41
    -0
      TachometerP.h
  11. +7411
    -0
      aclocal.m4
  12. +104
    -0
      autogen.sh
  13. +85
    -0
      bits.h
  14. +124
    -0
      bits_test.c
  15. +319
    -0
      bsd-base64.c
  16. +15
    -0
      bsd-base64.h
  17. +1
    -0
      cgps.1
  18. +842
    -0
      cgps.c
  19. +1
    -0
      cgpxlogger.1
  20. +280
    -0
      cgpxlogger.c
  21. +1464
    -0
      config.guess
  22. +1575
    -0
      config.sub
  23. +32014
    -0
      configure
  24. +779
    -0
      configure.ac
  25. +530
    -0
      depcomp
  26. +101
    -0
      dgnss.c
  27. +10
    -0
      dgpsip-servers
  28. +143
    -0
      dgpsip.c
  29. +256
    -0
      display.c
  30. +8
    -0
      display.h
  31. +408
    -0
      driver_proto.c
  32. +926
    -0
      drivers.c
  33. +508
    -0
      evermore.c
  34. +256
    -0
      floattest.c
  35. +1217
    -0
      garmin.c
  36. +402
    -0
      garmin_txt.c
  37. +172
    -0
      geoid.c
  38. +174
    -0
      gps.1
  39. +358
    -0
      gps.h
  40. +535
    -0
      gps.py
  41. +255
    -0
      gps.xml
  42. +111
    -0
      gpscat
  43. +83
    -0
      gpscat.1
  44. +102
    -0
      gpsctl.1
  45. +330
    -0
      gpsctl.c
  46. +157
    -0
      gpsctl.xml
  47. +488
    -0
      gpsd.8
  48. +1823
    -0
      gpsd.c
  49. +503
    -0
      gpsd.h
  50. +18
    -0
      gpsd.h-head
  51. +462
    -0
      gpsd.h-tail
  52. +115
    -0
      gpsd.hotplug
  53. +596
    -0
      gpsd.php
  54. +631
    -0
      gpsd.spec
  55. +631
    -0
      gpsd.spec.in
  56. +17
    -0
      gpsd.usermap
  57. +1022
    -0
      gpsd.xml
  58. +316
    -0
      gpsd_config.h.in
  59. +72
    -0
      gpsd_dbus.c
  60. +16
    -0
      gpsd_dbus.h
  61. +183
    -0
      gpsfake
  62. +112
    -0
      gpsfake.1
  63. +630
    -0
      gpsfake.py
  64. +163
    -0
      gpsfake.xml
  65. +85
    -0
      gpsflash.1
  66. +687
    -0
      gpsflash.c
  67. +64
    -0
      gpsflash.h
  68. +108
    -0
      gpsflash.xml
  69. +71
    -0
      gpsmm_test.cpp
  70. +260
    -0
      gpspacket.c
  71. +89
    -0
      gpspipe.1
  72. +298
    -0
      gpspipe.c
  73. +111
    -0
      gpspipe.xml
  74. +466
    -0
      gpsprof
  75. +124
    -0
      gpsprof.1
  76. +187
    -0
      gpsprof.xml
  77. +590
    -0
      gpsutils.c
  78. +212
    -0
      gpxlogger.c
  79. +80
    -0
      hex.c
  80. +252
    -0
      install-sh
  81. +338
    -0
      isgps.c
  82. +508
    -0
      italk.c
  83. +495
    -0
      italk.h
  84. +140
    -0
      libgps.3
  85. +711
    -0
      libgps.c
  86. +9
    -0
      libgps.pc.in
  87. +222
    -0
      libgps.xml
  88. +109
    -0
      libgpsd.3
  89. +9
    -0
      libgpsd.pc.in
  90. +175
    -0
      libgpsd.xml
  91. +863
    -0
      libgpsd_core.c
  92. +64
    -0
      libgpsmm.3
  93. +66
    -0
      libgpsmm.cpp
  94. +34
    -0
      libgpsmm.h
  95. +77
    -0
      libgpsmm.xml
  96. +6
    -0
      logextract
  97. +6860
    -0
      ltmain.sh
  98. +360
    -0
      missing
  99. +101
    -0
      mkgmtime_test.c
  100. +40
    -0
      mkinstalldirs

+ 9
- 0
AUTHORS View File

@@ -0,0 +1,9 @@
Remco Treffkorn <remco@rvt.com>
Derrick J. Brashear <shadow@dementia.org>
Russ Nelson <nelson@crynwyr.com>
Eric S. Raymond <esr@thyrsus.com>
Gary E. Miller <gem@rellim.com>
Jeff Francis <jeff@gritch.org>
Amaury Jacquot <sxpert@esitcom.org>
Chris Kuethe <chris.kuethe@gmail.com>
Ville Nuorvala <vnuorval@tcs.hut.fi>

+ 32
- 0
COPYING View File

@@ -0,0 +1,32 @@
BSD LICENSE

The GPSD code is Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by
Remco Treffkorn. Portions of it are also Copyright (c) 2005 by Eric S.
Raymond. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:<P>

Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.<P>

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.<P>

Neither name of the GPSD project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 147
- 0
INSTALL View File

@@ -0,0 +1,147 @@
Here are the steps for installing gpsd and verifying its performance:

0. The only prerequisites you will absolutely need to build the suite
are C and C++ compilers: C for the gpsd daemon itself and its client C
library, C++ for the C++ client-library wrapper. Having the following
optional components on your system will enable various additional
capabilities and extensions:

pthreads library -> support for PPS timekeeping on serial GPSes
DBUS -> gpsd will issue DBUS notifications
X windows + lesstif -> two test clients depend on this
ncurses -> two more test clients depend on this
Python -> most of the test and profiling tools are in Python

The build degrades gracefully in the absence of any of these. You should
be able to tell from configure messages which extensions you will get.

1. Start by making sure you can get data from your GPS, otherwise the later
steps will be very frustrating. In this command

stty -F /dev/ttyXXX ispeed 4800 && cat </dev/ttyXXX

replace ttyXXX with the filename of the port. This will probably be
either /dev/ttyUSB0 or /dev/ttyS0. When you run this command, you
should see text lines beginning with $ come to stdout (possibly after
a short initial burst of binary garbage). If you don't see this, you
may have OS-level problems with your serial support, but more likely
have the wrong device. Look again.

2. Ensure that device permissions will enable gpsd to read from and
write to GPS devices even after it drops root privileges. If you are
running Fedora Core you can skip this step, as the stock configuration
has the right properties.

gpsd requires two things: (1) that GPS devices have group read and
write enabled, and (2) all of them are have the same group ID as a
prototypical device, typically /dev/ttyS0 under Linux or /dev/tty00
under *BSD. It does not actually matter what the owning group is,
as gpsd will look this up on startup.

Before dropping privileges, gpsd will ensure that it has access to
devices given to it on the command line by forcing their group read
and write permissions on.

On a Linux with udev, check the files in /etc/udev/permissions.d to
ensure that /dev/tty* devices are all created with the same group
and with 0660 permissions.

When gpsd drops privileges, its default is to set uid to 'nobody' and
group to the owning group of the prototype device (the configure
option --enable-gpsd-user=foo will cause gpsd to change to 'foo'
instead).

If your system has the Linux hotplug facility installed you can skip
the permission-setting part; the hotplug scripts will force the
permissions for you. You still have to make sure all the tty devices
are in the same group.

3. Build gpsd from source (skip this step if you have installed a gpsd
binary package).

You will need to have either Motif or LessTif installed in order for
xgps and xgpsspeed to build; if you don't, you'll get some error
resembling "Xm/Xm.h: No such file or directory". If you're on a Linux
system, you may already have LessTif. Source code is available
from <http://www.lesstif.org/>.

Under Ubuntu, you will require libmotif-dev, libxp-dev and libxaw7-dev
in addition to the standard build-support packages. You can get
all the build prerequisites intalled with "apt-get build-dep gpsd".

To build from source, run ./autogen.sh (or sh autogen.sh if the
script does not have execute permission). Mac OS X users may
need to do "./autogen.sh --x-includes=/usr/X11R6/include"

Note: if you are going to use the RTCM-104 support, you should compile
with gcc4; if you don't have it installed as your default
compiler, do this by specifying CC=gcc4 before the autogen.sh
command. The rtcm.c file confuses the gcc-3.4.[23] optimizer
at -O2 level, making it generate incorrect code.

Then run make: libgps.so, gpsd, xgps, and xgpsspeed will be
built. Copy the app-defaults files xgps.ad and xgpsspeed.ad to your
home directory or to the system-wide X app-defaults directory.

4. Start gpsd. You'll need to give it as an argument a path to
a serial or USB port with a GPS attached to it.

5. Once gpsd is running, telnet to port 2947. Type 'f' to see what
device it will query. If you need to change the device, use 'f='
to do so (see the manual page for details). Now plug in your GPS.

6. Type "wr" to start raw and watcher modes. You should see NMEA data
(text lines beginning with $) spewing out. You will also see lines
with a GPSD prefix; these are sentence translations in GPSD protocol.

Note that until your GPS has acquired a fix, typing "p" to get position
will only return this:

GPSD,P=?

This response does not mean that gpsd is broken or that the GPS is not
sending data, merely that gpsd has not yet seen any *valid* position data.
You will have to wait for the GPS to acquire satellite lock. If you have
raw or watcher mode on, it should be obvious when you get a lock.

7. Start the xgps client. Calling it with no arguments should do the right
thing. You should see a GUI panel with position/velocity-time information,
and a satellite display. The displays won't look very interesting until
the GPS acquires satellite lock.

8. Now that you've verified that the code is working, "make install"
will install it it in the system directories. "make uninstall" will
undo this.

(You won't need to "make install" if you installed from a binary package.)

9. Check out the list of supported hardware at

http://gpsd.berlios.de/hardware.html

If your GPS isn't on the list, please send us information to add a new
line to the table. Directions are included on that page.

We can also use updates of the latest version number known to work with
hardware already supported.

10. Note for small embedded systems and those without threading. It is
possible to build gpsd without thread support if you configure with
--disable-pps. You'll lose support for updating the clock from PPS pulses.
It's also possible to build without Python via --disable-python, in which
case you'd build won't make Python libraries and "make install" won't
try to install Python tools.

11. Note for systems using DBUS: gpsd includes support for shipping fixes
as DBUS notifications, but it is not compiled in by default. Configure
with the option "--enable-dbus" to get it working.

12. The distribution includes a PHP script that you can use to
generate a PHP status page for your GPS. You will need php and php-gd
installed. To install it, copy the file 'gpsd.php' to your HTTP
document directory. The first time it's invoked, it will generate a
file called 'gpsd_config.inc' containing configuration information;
edit to taste. Note that for the Google Maps feature work you need
to set a valid Google API key in your config file.



+ 466
- 0
Makefile.am View File

@@ -0,0 +1,466 @@
# Automake description for gpsd
# $Id: Makefile.am 4683 2008-02-17 02:25:36Z ckuethe $

#SUBDIRS = contrib

#
# Build stuff depending on Motif
#
if HAVE_MOTIF
MOTIF_PROGS = xgps xgpsspeed
endif

XMLTO = xmlto

if HAVE_DBUS
INCLUDES = $(DBUS_CFLAGS) $(DBUS_GLIB_CFLAGS) -DDBUS_API_SUBJECT_TO_CHANGE=1
DBUSPROGS = gpxlogger
gpxlogger_LDADD = $(DBUS_GLIB_LIBS) libgps.la -lm
endif

if HAVE_RTCM104
RTCM104PROGS = rtcmdecode
RTCM104PAGES = rtcmdecode.1
endif


if HAVE_NCURSES
CURSESPROGS = cgps sirfmon
endif
bin_PROGRAMS = $(DBUSPROGS) $(MOTIF_PROGS) $(RTCM104PROGS) $(CURSESPROGS) gpsctl gpspipe gpsflash cgpxlogger
sbin_PROGRAMS = gpsd
check_PROGRAMS = bits_test gpsmm_test packet_test mkgmtime_test
if HAVE_PYTHON
dist_bin_SCRIPTS = gpsprof gpsfake gpscat
python_PYTHON = gps.py gpsfake.py
nodist_python_PYTHON = gpspacket.so
PYTHONPAGES = gpsprof.1 gpsfake.1 gpscat.1
endif

#
# Build xgps
#
xgps_SOURCES = display.c display.h xgps.c
xgps_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(XM_LIBS) $(XT_LIBS) $(X_LIBS) $(X_PRE_LIBS) libgps.la -lm $(LIBPTHREAD)

#
# Build xgpsspeed
#
xgpsspeed_c_sources = \
xgpsspeed.c \
Tachometer.c \
TachometerP.h \
Tachometer.h
xgpsspeed_SOURCES = \
$(xgpsspeed_c_sources) \
xgpsspeed.icon
xgpsspeed_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(XAW_LIBS) $(XM_LIBS) $(X_LIBS) $(X_PRE_LIBS) libgps.la -lm $(LIBPTHREAD)

#
# Build cgps
#
cgps_SOURCES = cgps.c
cgps_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) -lncurses libgps.la -lm $(LIBPTHREAD)

#
# Build cgpxlogger
#
cgpxlogger_SOURCES = cgpxlogger.c
cgpxlogger_LDADD = $(LIBC) $(LIBNSL) $(LIBSOCKET) libgps.la -lm $(LIBPTHREAD)

#
# Build gpsd
#
gpsd_c_sources = gpsd_dbus.c gpsd.c
gpsd_SOURCES = $(gpsd_c_sources) gpsd_dbus.h
gpsd_LDADD = $(DBUS_LIBS) $(LIBM) libgps.la -lm $(LIBPTHREAD)

#
# Build gpsctl
#
gpsctl_SOURCES = gpsctl.c
gpsctl_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD)

#
# Build gpspipe
#
gpspipe_SOURCES = gpspipe.c
gpspipe_LDADD = $(DBUS_LIBS) $(LIBM) libgps.la -lm

#
# Build sirfmon
#
sirfmon_SOURCES = sirfmon.c
sirfmon_LDADD = $(LIBM) -lncurses libgps.la -lm $(LIBPTHREAD)

#
# Build rtcmdecode
#
rtcmdecode_SOURCES = rtcmdecode.c
rtcmdecode_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD)

#
# Build gpsflash
#
gpsflash_SOURCES = gpsflash.c gpsflash.h sirfflash.c
gpsflash_LDADD = $(LIBM) libgps.la -lm

#
# Build shared libraries
#
libgps_la_LDFLAGS = -version-number 17:0:0
lib_LTLIBRARIES = libgps.la

libgpsd_c_sources = \
netlib.c \
nmea_parse.c \
serial.c \
libgpsd_core.c \
subframe.c \
ntpshm.c \
libgps.c \
packet.c \
gpsutils.c \
geoid.c \
dgnss.c \
dgpsip.c \
ntrip.c \
sirf.c \
report.c \
isgps.c \
rtcm.c \
srecord.c \
bsd-base64.c \
strl.c \
hex.c \
drivers.c \
zodiac.c \
ubx.c \
garmin.c \
garmin_txt.c \
tsip.c \
evermore.c \
italk.c \
navcom.c

libgpsd_h_sources = \
italk.h \
bsd-base64.h \
timebase.h \
bits.h \
packet_names.h \
rtcm.h \
gpsd.h

BUILT_SOURCES = packet_names.h gpsd.h
packet_names.h: packet_states.h
sed -e '/^ *\([A-Z][A-Z0-9_]*\),/s// "\1",/' -e '/_states/s//_names/' < `test -f 'packet_states.h' || echo '$(srcdir)/'`packet_states.h > packet_names.h

gpsd.h: gpsd.h-head gpsd.h-tail gpsd_config.h
cp gpsd.h-head gpsd.h
grep VERSION gpsd_config.h >>gpsd.h
grep ENABLE gpsd_config.h >>gpsd.h
cat gpsd.h-tail >>gpsd.h

libgps_la_SOURCES = $(libgpsd_c_sources) $(libgpsd_h_sources) \
rtcm.h libgpsmm.cpp packet_states.h
nodist_libgps_la_SOURCES = packet_names.h
libgps_la_LIBADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(LIBPTHREAD)

#
# Build Python binding
#
# install may require --root depending on what you're doing.
# python setup.py install --root=$DESTIR --prefix=$PREFIX
if HAVE_PYTHON
PYEXTENSIONS = gpspacket.so
noinst_SCRIPTS = gpspacket.so setup.py

gpspacket.so: gpspacket.c libgps.la
(pwd="`pwd`"; cd $(srcdir) && $(PYTHON) setup.py build_ext --build-lib "$$pwd" --build-temp "$$pwd/build" --include-dirs "$$pwd")
endif
# Clean up after Python
clean-local:
rm -rf build

#
# Build gpsmm_test
#
gpsmm_test_SOURCES = gpsmm_test.cpp
gpsmm_test_LDADD = $(LIBC) libgps.la -lm

#
# Build bits_test tester
#
bits_test_SOURCES = bits_test.c
bits_test_LDADD = $(LIBC) libgps.la

#
# Build packets tester
#
packet_test_SOURCES = packet_test.c
packet_test_LDADD = $(LIBC) libgps.la -lm

#
# Build packets tester
#
mkgmtime_test_SOURCES = mkgmtime_test.c
mkgmtime_test_LDADD = $(LIBC) libgps.la -lm

if HAVE_XSLT_PROCESSOR
#
# Create Manpages
#
man_MANS = \
gpsd.8 \
gps.1 \
xgps.1 \
xgpsspeed.1 \
cgps.1 \
cgpxlogger.1 \
libgps.3 \
libgpsmm.3 \
libgpsd.3 \
sirfmon.1 \
$(RTCM104PAGES) \
$(PYTHONPAGES) \
gpsctl.1 \
gpspipe.1 \
gpsflash.1 \
rtcm-104.5 \
srec.5

.xml.1:
$(MANGENERATOR) $(MANFLAGS) $(MANTARGET) $<

.xml.3:
$(MANGENERATOR) $(MANFLAGS) $(MANTARGET) $<

.xml.5:
$(MANGENERATOR) $(MANFLAGS) $(MANTARGET) $<

.xml.8:
$(MANGENERATOR) $(MANFLAGS) $(MANTARGET) $<

gpsd.8: gpsd.xml

gps.1 xgps.1 xgpsspeed.1 cgps.1 cgpxlogger.1: gps.xml

libgps.3: libgps.xml

libgpsmm.3: libgpsmm.xml

libgpsd.3: libgpsd.xml

gpsctl.1: gpsctl.xml

gpscat.1: gpsctl.xml

gpsprof.1: gpsprof.xml

gpsfake.1: gpsfake.xml

sirfmon.1: sirfmon.xml

gpspipe.1: gpspipe.xml

rtcmdecode.1: rtcmdecode.xml

rtcm-104.5: rtcm-104.xml

srec.5: srec.xml

gpsflash.1: gpsflash.xml

endif

noinst_HEADERS = ubx.h
nodist_include_HEADERS = gpsd.h
include_HEADERS = gps.h libgpsmm.h

EXTRA_DIST = \
autogen.sh \
README \
INSTALL \
COPYING \
TODO \
AUTHORS \
dgpsip-servers \
floattest.c \
gpsd.php \
gpsd.xml \
gpsd.h-head \
gpsd.h-tail \
gps.xml \
libgpsd.xml \
libgps.xml \
libgpsmm.xml \
gpsprof.xml \
gpsfake.xml \
gpsctl.xml \
sirfmon.xml \
gpspipe.xml \
rtcmdecode.xml \
rtcm-104.xml \
srec.xml \
gpsflash.xml \
$(man_MANS) \
xgps.ad \
xgpsspeed.ad \
gpsd.spec.in \
gpsd.spec \
gpsd.hotplug \
gpsd.usermap \
valgrind-audit \
valgrind-suppressions \
gpspacket.c \
driver_proto.c \
logextract \
striplog \
setup.py \
packet_states.h \
libgps.pc.in \
libgpsd.pc.in

CLEANFILES = $(BUILT_SOURCES) floattest *.core $(PYEXTENSIONS)

pkgconfig_DATA = libgps.pc libgpsd.pc
pkgconfigdir = $(libdir)/pkgconfig

# This is not distributed
libgps: libgps.c .libs/libgps.a
$(CC) $(CFLAGS) -o libgps -lm -DTESTMAIN $(LIBPTHREAD) -g libgps.c .libs/libgps.a

# Report splint warnings
SPLINTOPTS = -I/usr/include/dbus-1.0/
splint:
@echo "Running splint on daemon and libraries..."
@echo "Expect 'gpsd.c:230:39: Line expects to suppress 1 error, found 0 errors'"
-splint $(SPLINTOPTS) -redef $(gpsd_c_sources) $(libgpsd_c_sources)
@echo "Running splint on xgps..."
-splint $(SPLINTOPTS) -exportlocal $(xgps_SOURCES)
@echo "Running splint on cgps..."
-splint $(SPLINTOPTS) -exportlocal $(cgps_SOURCES)
@echo "Running splint on xgpsspeed..."
-splint $(SPLINTOPTS) -exportlocal $(xgpsspeed_c_sources)
@echo "Running splint on gpsctl..."
-splint $(SPLINTOPTS) $(gpsctl_SOURCES)
@echo "Running splint on sirfmon..."
-splint $(SPLINTOPTS) $(sirfmon_SOURCES)
@echo "Running splint on gpspipe..."
-splint $(SPLINTOPTS) $(gpspipe_SOURCES)
@echo "Running splint on rtcmdecode..."
-splint $(SPLINTOPTS) -exportlocal rtcmdecode.c
@echo "Running splint on gpsflash..."
-splint $(SPLINTOPTS) $(gpsflash_SOURCES)
@echo "Running splint on bits_test test harness..."
-splint $(SPLINTOPTS) $(bits_test_SOURCES)
@echo "Running splint on packet_test test harness..."
-splint $(SPLINTOPTS) $(packet_test_SOURCES)

# Bogon-checking the Python tools
pychecker:
for f in gps.py gpsfake.py; do pychecker $$f; done

version:
@echo $(VERSION)

#
# Regression tests begin here
#
# Note that the *-makeregress targets re-create the *.log.chk source
# files from the *.log source files.
#
# These require gcc4; use of the math coprocessor's on-board trig functions
# apparently increases the accuracy of computation in a way that affects
# the low-order digits of the track field in the O response.

# Regression-test the daemon
gps-regress: gpsd
$(srcdir)/regress-driver -t $(srcdir)/test/stable/*.log

# Test that super-raw mode works. Compare each logfile against itself
# dumped through the daemon running in R=2 mode. (This test is not
# included in the normal regressions.)
raw-regress:
$(srcdir)/regress-driver -r $(srcdir)/test/stable/*.log

# Build the regression tests for the daemon.
gps-makeregress: gpsd
$(srcdir)/regress-driver -b $(srcdir)/test/stable/*.log

# Regression-test the RTCM decoder.
rtcm-regress: rtcmdecode
@echo "Testing RTCM decoding..."
@mkdir -p test
@for f in $(srcdir)/test/*.rtcm; do \
echo "Testing $${f}..."; \
$(srcdir)/rtcmdecode <$${f} >test/test.chk; \
diff -ub $${f}.chk test/test.chk; \
done; \
rm test/test.chk

# Rebuild the RTCM regression tests.
rtcm-makeregress: rtcmdecode
@for f in $(srcdir)/test/*.rtcm; do \
$(srcdir)/rtcmdecode < $${f} > $${f}.chk; \
done

# Regression-test the packet getter.
packet-regress: packet_test
@echo "Testing detection of invalid packets..."
@$(srcdir)/packet_test | diff -u $(srcdir)/test/packet.test.chk -

# Rebuild the packet-getter regression test
packet-makeregress: packet_test
@mkdir -p test
$(srcdir)/packet_test >test/packet.test.chk

# Test RTCM encoding using passthrough mode.
undump-regress: rtcmdecode
@echo "Testing RTCM encoding..."
@mkdir -p test
@$(srcdir)/rtcmdecode -p < $(srcdir)/test/undump.sample > test/undump.test
@diff -u $(srcdir)/test/undump.sample test/undump.test
@rm test/undump.test

# Regression-test the calendar functions
time_regress: mkgmtime_test
mkgmtime_test

# Do all normal regression tests
testregress: gps-regress rtcm-regress packet-regress undump-regress time_regress
@echo "Regressions complete."

#
# Productions for testing unstable drivers.
#

unstable-regress: gpsd
./regress-driver -t $(srcdir)/test/unstable/*.log

unstable-makeregress: gpsd
./regress-driver -b $(srcdir)/test/unstable/*.log


# Release machinery begins here
#
# This is how to ship a release to Berlios incomoing.
# It requires developer access verified via ssh.
#
upload-ftp:
sha1 gpsd-$(VERSION).tar.gz >gpsd.sum
lftp -c "mput gpsd-$(VERSION).tar.gz gpsd.sum" ftp://ftp.berlios.de/incoming

#
# This is how to tag a release for the SVN repository.
# It requires developer access verified via ssh.
#
REPO=http://svn.berlios.de/svnroot/repos/gpsd
svn-tag:
svn copy $(REPO)/trunk $(REPO)/tags/release-$(VERSION) \
-m "Tagged for external release $(VERSION)"
#
# Ship a release, providing all regression tests pass.
#
ship: testregress dist upload-ftp svn-tag

+ 1748
- 0
Makefile.in
File diff suppressed because it is too large
View File


+ 123
- 0
README View File

@@ -0,0 +1,123 @@
$Id: README 4447 2007-12-05 11:22:48Z esr $

COPYRIGHT
=========

This software (gpsd) released under the terms and conditions of the BSD
License, a copy of which is included in the file COPYING.

GENERAL
=======

gpsd is a userland daemon acting as a translator between GPS or
Loran-C receivers and clients. gpsd listens on port 2947 for clients
requesting position/time/velocity information. The receivers are
expected to generate position information in a well-known format -- as
NMEA-0183 sentences, SiRF binary, Rockwell binary, Garmin binary
format, or other vendor binary protocols. gpsd takes this
information from the GPS and translates it into something uniform and
easier to understand for clients. The distribution includes sample
clients, application interface libraries, and test/profiling tools.

There is a project site for gpsd at <http://gpsd.berlios.de/>.
Look there for updates, news, and project mailing lists. See that
website for a list of GPS units known to be compatible.

See the file INSTALL for installation instructions and some tips on
how to troubleshoot your installation.

Distro integrators: An RPM spec file is included in the gpsd
distribution. It wants to set up a hotplug script to notify gpsd
when a potential GPS device goes active and should be polled. The
goal is zero configuration; users should never have to tell gpsd how
to configure itself. If you can't use RPM, use what you see in the
specfile as a model.

1.X CREDITS
===========

Remco Treffkorn designed and originated the code.

Russ Nelson maintained gpsd for a couple of years.

Carsten Tschach's gpstrans-0.31b code was the original model for nmea_parse.c.

Bob Lorenzini <hwm@netcom.com> provided testing and feedback.

Brook Milligan <brook@trillium.NMSU.Edu> combined gpsd and gpsclient
into one package and autoconfiscated it.

Derrick J. Brashear <shadow@dementia.org> (KB3EGH) added code for the
EarthMate DeLorme. He also added "incredibly gross code to output
NMEA sentences" (his own words :-) He also did the first cut at
DGPS support (see http://www.wsrcc.com/wolfgang/gps/dgps-ip.html),
for the Earthmate.

Curt Mills <BowHunter@mail.com> (WE7U) furthered the dgps support,
writing the portion for other GPS receivers.

None of these people are active in 2.X, through Remco de-lurks on the
mailing list occasionally.

2.X CREDITS
===========

Eric S. Raymond drastically rewrote this code to clean it up and extend it.
The 2.X architecture has become significantly different and far more
modularized.

His new features include:
* Documentation (what a concept!)
* Cleaned up, simplified command-line options.
* Now understands the GLL (Geographic position - Latitude, Longitude)
sentence from NMEA 3.0.
* Now parses both the NMEA 3.01 and pre-3.01 variants of the VTG sentence
correctly.
* New 'y' command supports satellite location -- it should no longer ever
be necessary for clients to go to raw mode unless they want to monitor and
and log the NMEA stream itself.
* New 'w' command toggles 'watcher' mode. In watcher mode gpsd ships
a gpsd-style response for each incoming sentence as if the client
had just sent all commands that asked for data contained in the sentence.
* New 'x' command allows the client to query whether or not the GPS
is on-line.
* Massive refactoring -- one main loop now calls a self-contained
driver object for each type.
* The GPS-bashing code the daemon uses can now be directly linked as a
library, libgpsd(3).
* C and Python libraries are available to encapsulate the client side of
querying gpsd, see libgps(3).
* Cleaned-up error reporting, we don't use syslog when running in foreground
but send all error and status messages to the tty instead.
* Added -n option to do batch monitoring of GPSes.
* xgpsspeed is working again; xgps has been seriously reworked and improved.
* RPMs which include installation of gpsd to start up at boot time
are available.
* New gpsprobe program probes the capabilities of GPSes and generates
error scattergrams from fixes. (Later this moved to gpsprof.)
* Autobauding, self-configuration, and hotplugging. gpsd can now get
its device from a hotplug script, and figures out itself which baud
rate to use and what the GPS's device type is.
* More new commands: 'I', 'U', 'E', 'B', 'Z'. See the docs.
* Support for SiRF binary mode.
* Support for multiple devices.
* Other test tools -- gpsfake, gpscat.

Chris Kuethe <ckuethe@mail.berlios.de> maintains the OpenBSD port, shipped
the 2.34 release, is our SiRF and low-level protocols expert, and does a
lot of general hacking and support.

Gary Miller <gem@rellim.com> wrote the driver for Garmin binary protocol.

Amaury Jacquot <sxpert@esitcom.org> added DBUS support.

Ville Nuorvala <vnuorval@tcs.hut.fi> wrote the NTRIP support.

We are delighted to acknowlege the assistance of Carl Carter, a field
application engineer at SiRF. He assisted us with the correction and
tuning of the SiRF binary-protocol driver, shedding a good deal of
light on murky aspects of the chip's behavior.

We are delighted to acknowlege the assistance of Timo Ylhainen, VP of
Software Operations at Fastrax. He clarified a number of points about
the iTalk protocol, helping to further development of iTalk support.

+ 331
- 0
TODO View File

@@ -0,0 +1,331 @@
$Id: TODO 4671 2008-01-21 15:36:55Z esr $

This is the gpsd to-do list. If you're viewing it with Emacs, try
doing Ctl-C Ctl-t and browsing through the outline headers. Ctl-C Ctl-a
will unfold them again.

For contribution guidelines and internals documentation, please see
<http://gpsd.berlios.de/hacking.html>.

The list of bugs exposed by gpsd in other software has moved to
<http://gpsd.berlios.de/upstream-bugs.html>.

** Bugs in gpsd and its clients:

*** Support for the True North magnetic compass is currently broken

Massimo Burcheri reported that it broke somewhere between rev 3654 and
3722. We think this is a shallow bug, but we can't fix it without
test hardware. If TNT support is a problem for you, and you can't
fix the driver yourself and send us the patch, contact Bill Powell
<bpowell@tntc.com> at True North Technologies and tell him he needs
to reverse his refusal to send us an eval unit.

** To do:

*** libgps should try to automatically try to reconnect when a poll fails

Petter Reinholdtsen suggests:

At the moment, when a gpsd client using libgps is connected to the
gpsd server, and the server is restarted, the client looses the
connection and do not update any more.

It would be nice if the gps_poll() and gps_query() would try to
reconnect to the server if the read() and write() calls on the tcp
socket fail.

To test this, start gpsd first (/etc/init.d/gpsd start), xgps second,
and then restart gpsd (/etc/init.d/gpsd restart). The xgps client
will fail to update any more.

I realised how nice this feature would be while comparing the xgps
client to the roadgps client (part of the roadmap package). The
roadgps client would reconnect to the new server and keep updating as
soon as the server was available. :)

On second thought, and after discussing this on the gpsd mailing list,
I believe the reconnect need to be handled by the applications in
addition to the library. Applications will commonly use the file
descriptor to detect incoming data, and this file descriptor will
change on reconnect.

So I rephrase my wish, and ask for reconnect funcionality in xgps
instead. It will make sure the library support reconnects, and also
provide an example for other clients using the library.

(ESR thinks maybe this ought to be done at library level anyway, with
users warned that the gps_fd member of the gps_data_t structure may
change on reconnect and shouldn't be cached. This wouldn't be hard to
implement, but it would change gps_data_t and require a library
version bump.)

This is Berlios FR #3789.

*** Optimize the use of gpsd_hexdump and gpsd_report

These functions still consume a significant (ie. non-zero) fraction of
CPU time at -D0 or -D1. Possible solutions include a wrapper around
gpsd_hexdump to only dump when the debug level is high enough, or
modifying gpsd_report to handle the hexdump call. This may require (at
worst) a library version number increment, or at least changing every
invocation of gpsd_hexdump. Not something to be done lightly.

*** Change O output precision to %.9f for degrees and %.3f for meters

This corresponds to 1mm accuracy, which is better than the horizontal
accuracy of RTK GPS. This will be revisited; receivers are commercially
available that claim to have 0.1mm accuracy

*** Full Python wrapper for libgpsd

This would be useful for test code of all kinds.

*** New features for xgps.

Add J option checkbox. Maybe embed the speedometer widget from
xgpspeed in some of the unused space and nuke xgpsspeed.

*** Per-driver restore of changed config settings on exit.

This is a solved problem for generic NMEA, EverMore, TripMate,
EarthMate, TNTC, Zodiac, and RTCM104 drivers (if only because they
don't configure any device setting).

The SiRF driver now restores NMEA when necessary. It also restores
some (but not all) of the things it tweaks in binary mode -- at the
moment, just the Navigation Parameters from message 0x13. With more
work, we should be able to do a full revert.

The TSIP driver changes its per-cycle sentence inventory and thus
needs some state-restore logic. This can be done; the same packet 0x35
we use to configure it can be sent in a no-argument mode to query
the current sentence mix for later restore.

The FV18 changes its per-cycle sentence inventory to include GSAs. It
is possible to query that inventory, though we don't have code to do
it yet.

Garmin devices are a mess. We reconfigure those heavily, and we
don't know if there's any way to capture their configuration state
before we do it.

The iTrax02 driver sets SYNCMODE to start navigation messages without
checking to see if it's already on, and stops navigation methods on
wrapup. It also forces the set of sentences issued. There doesn't
seem to be any way to query these settings.

*** Merge cgps and xgps

Possibly cgps and xgps should merge into a single test client that honors the
GPSD_UNITS environment variable and chooses its UI mode depending on
whether or not it's running under X. There is controversy about this
proposal on the dev list.

*** send/expect for the NMEA driver initializer

We've had one report of a GPS, the Garmin GPS-10, which gpsd puts in a
bad state because the device chokes on having all of our NMEA probe strings
shoved at it without having time to respond. A simple send-expect
function (ship given string, wait until specified reply arrives or time
out) would solve this problem and might help avoid problems with other
GPSes we haven't encountered yet.

*** SiRF firmware uploader

Chris Kuethe has shipped a 0.0 pre-alpha version. It is not yet
resolved whether SiRF Technology will allow us to ship the
binary loader code needed to actually use it.

*** uBlox firmware uploader

uBlox does make firmware updates available on their website and a cursory
inspection suggests that their flash process should plug directly in to
gpsflash - they use the same three stage process as SiRF: send a binary
command to enter programming mode, send a tiny reflash bootstrap program
and then send the actual firmware image.

*** Industry-standard format dumping of raw satellite data

It would be useful to be able to extract RINEX (or some other standard)
format data from any GPS device that can report pseudoranges etc. This
belongs in the daemon because the device drivers are already doing the
packet-cracking needed to get the data off the chips.

Several commodity chipsets (ANTARIS, iTrax3, SiRF and Trimble) readily
output enough data to make this a chore, rather than a hard problem.

It has been suggested one way to do this is to have a generic structure
in memory and corresponding output message with clock, doppler carrier
phase and pseudoranges. This message is then reformatted by a client
program. There are numerous formats for this information, and it would
be easier to adapt to new formats if the formatting and use was handled
by something other than the gpsd daemon. Currently the RT-IGS format is
looking like the favorite for implementation; it's a fairly lightweight
protocol, flexible enough to handle all the quantities required, and it
is actually in use in production reference networks. RT-IGS is also a
packet-oriented format, rather than a file-oriented format like RINEX.

*** RTCM support.

We have an RTCM packet decoder, and untested scratch code to serve
RTCM packets to port 2101. Here's the plan for the rest of it:

1) Inversion needs to be done somewhere in the encoding logic.

2) Wolfgang's decoder-hardening patches.

3) Test productions. I have one that tests dumping and one that uses
passthrough mode to test that pack() and repack() are inverse. We
should have an undumping torture test.

4) What about rtcm_output_magnavox() anyway? Should that be made
available as an output mode of rtcmdecode and documented?

5) Extend the test framework so we can verify RTCM service.

6) Generate and broadcast RTCM corrections from an attached device?
Might not be possible -- appears to need nanosecond timing.

*** Do the research to figure out just what is going on with status bits

NMEA actually has *four* kinds of validity bits: Mode, Status, the
Active/Void bit (some sources interpret 'V' as 'Navigation receiver
warning'), and in later versions the FAA indicator mode. Sentences
that have an Active/Void send V when there is no fix, so the position
data is no good.

Let's look at which sentences send what:

GPRMC GPGLL GPGGA GPGSA
Returns fix Yes Yes Yes No
Returns status No Yes Yes No
Returns mode No No No Yes
Returns A/V Yes Yes No No

In addition, some sentences use empty fields to signify invalid data.

My first conclusion from looking at this table is that the designers
of NMEA 0183 should be hung for galloping incompetence. But never mind that.
What are we to make of this mess?

The fact that the FV18 sends GPRMC/GPGLL/GPGGA but not GPGSA
argues that GPGSA is optional. I don't see how it can be, since it
seems to be the only status bit that applies to altitude. Just how are
we supposed to know when altitude is valid if it doesn't ship GSA?
Can a receiver ever ship a non-empty but invalid altitude?

Which of these override which other bits? I don't think status is ever
nonzero when mode is zero. So status overrides mode. What other such
relationships are there?

News flash: it develops that the "Navigation receiver warning" is
supposed to indicate a valid fix that has a DOP too high or fails
an elevation test.

** Future features (?)

*** iTalk support

There is a minimally functional driver for the Fastrax iTalk3 protocol.
It is still very much a work in progress. It is now compiled in by default
so that we can collect bug reports. Version 3 of iTalk is not backwards
compatible; we do not anticipate supporting previous versions unless
someone requests it and is able to provide us hardware.

*** Navcom support

Initial support for the Navcom binary protocol has been committed to
allow for in-tree development. It is compiled in by default.

*** UBX support

There is a minimally functional driver for the uBlox UBX protocol. It is
still very much a work in progress. It is now compiled in by default so
that we can collect bug reports.

*** Support for more survey / professional / up-scale receivers.

Devices such as the Javad JNSCore, Hemisphere Crescent, Septentrio
AsteRx and PolaRx, NovAtel Superstar2 and OEMV, Thales (Magellan
Professional) AC12 and DG14 would all be welcome. Of course, these
are not $50 usb mice...

*** Audio cues in the client when the fix status changes

Calum writes:
>Is it possible to add functionality (with a switch to enable it to
>avoid annoying those that don't want it) so that beeps indicate NO
>FIX, FIX, and OFFLINE status changes?
>
>For example - I run cgps and my laptop battery doesn't always supply
>my PS2 port-powered GPS device with enough power, and it goes into
>OFFLINE mode. As I can't drive, and check my laptop all the time, if
>it emitted 5 1 second beeps when it went OFFLINE, it would be a handy alert.
>
>Similarly, a PCMCIA "eject" 2 beeps for NO FIX, and a PCMCIA "happy" 2
>beeps when it gets a fix again?
>
>Or something like that.

This is a good idea for supporting hands-free operation, e.g. while driving.

It would be an easy first project for somebody who wants to get into
the client code.

*** Set the system time zone from latitude/longitude

If we're going to give gpsd the capability to set system time via
ntpd, why not let it set timezone as well? A good thing for hackers
travelling with laptops!

The major issue here is that I have not yet found code, or a
database, that would allow mapping from lon/lat to timezone.
And the rules change from year to year.

Actually this should be built as a specialized client, as some
people won't want it.

From <http://www.linuxsa.org.au/tips/time.html>:

The timezone under Linux is set by a symbolic link from
/etc/localtime[1] to a file in the /usr/share/zoneinfo[2] directory
that corresponds with what timezone you are in. For example, since I'm
in South Australia, /etc/localtime is a symlink to
/usr/share/zoneinfo/Australia/South. To set this link, type:

ln -sf ../usr/share/zoneinfo/your/zone /etc/localtime

Replace your/zone with something like Australia/NSW or
Australia/Perth. Have a look in the directories under
/usr/share/zoneinfo to see what timezones are available.

[1] This assumes that /usr/share/zoneinfo is linked to /etc/localtime as it is under Red Hat Linux.

[2] On older systems, you'll find that /usr/lib/zoneinfo is used
instead of /usr/share/zoneinfo.

Changing the hardlink will, of course, update the system timezone for
all users. If I were designing this feature, I'd ensure that the
system timezone can be overridden by a user-set TZ, but I don't know
if it actually works that way.

If I'm reading the tea leaves correctly, this functionality is actually
embedded in the GCC library version of tzset(), so the same method will
work on any system that uses that.

Problem: system daemons use the timezone set when they start up. You
can't get them to grok a new one short of rebooting.

Sources:

Sources for Time Zone and Daylight Saving Time Data
http://www.twinsun.com/tz/tz-link.htm

Free time-zone maps of the U.S.
http://www.manifold.net/download/freemaps.html

Local variables:
mode: outline
paragraph-separate: "[ ]*$"
end:

+ 581
- 0
Tachometer.c View File

@@ -0,0 +1,581 @@
/* $Id: Tachometer.c 4427 2007-10-16 13:40:03Z esr $ */
/*
* Tachometer Widget Implementation
*
* Author: Kazuhiko Shutoh, 1989.
* Revised by Shinji Sumimoto, 1989/9 (xtachos)
* Modifications : ilham@mit.edu (July 10 '90)
* Cleaned up and simplified by Eric S. Raymond, December 2004.
*/
#include <sys/types.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <TachometerP.h>
#include <math.h>
#include "gpsd_config.h" /* must define UNUSED */

#define D2R 0.0174532925199432957692369076848861271 /* radians = pi/180 */

/****************************************************************
*
* Full class record constant
*
****************************************************************/

typedef struct {
unsigned char digit[7];
} DigitRec;

typedef struct {
int nofline;
XPoint point_list[5];
} StringRec;

/*@ +charint @*/
/* Number character database - like an LED */
static DigitRec num_segment[] = {
{{1,1,1,1,1,1,0}},
{{0,1,1,0,0,0,0}},
{{1,1,0,1,1,0,1}},
{{1,1,1,1,0,0,1}},
{{0,1,1,0,0,1,1}},
{{1,0,1,1,0,1,1}},
{{1,0,1,1,1,1,1}},
{{1,1,1,0,0,0,0}},
{{1,1,1,1,1,1,1}},
{{1,1,1,1,0,1,1}}};

static XSegment offset[] = {
{-10,-10, 10,-10},
{ 10,-10, 10, 0},
{ 10, 0, 10, 10},
{ 10, 10,-10, 10},
{-10, 10,-10, 0},
{-10, 0,-10,-10},
{-10, 0, 10, 0}};

/*@ -initallelements @*/
/* " X 10 %" character database */
static StringRec char_data[] = {
{ 2, /* "X" */
{{-17, -5},
{-7, 5}}},
{ 2,
{{-7, -5},
{-17, 5}}},
{ 2, /* "1" */
{{-2, -5},
{-2, 5}}},
{ 5, /* "0" */
{{2, -5},
{12, -5},
{12, 5},
{2, 5},
{2, -5}}}};
#if 0
{{{{ {2, -5}}},
{ 5, /* "%" */
{{17, -5},
{20, -5},
{20, -2},
{17, -2},
{17, -5}}},
{ 2,
{{27, -5},
{17, 5}}},
{5,
{{24, 2},
{27, 2},
{27, 5},
{24, 5},
{24, 2}}}};
#endif
/*@ -initallelements @*/
/*@ -charint @*/

/*@ -nullderef -immediatetrans -type -nullassign @*/
#define offst(field) XtOffset(TachometerWidget, field)
static XtResource resources[] = {
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offst(tachometer.scale), XtRString, "XtDefaultForeground"},
{XtNtachometerCircleColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
offst(tachometer.circle), XtRString, "XtDefaultForeground"},
{XtNtachometerNeedleColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
offst(tachometer.needle), XtRString, "XtDefaultForeground"},
{XtNtachometerNeedleSpeed, XtCtachometerNeedleSpeed, XtRInt,
sizeof(int), offst(tachometer.speed), XtRImmediate, (caddr_t) 1},
{XtNvalue, XtCValue, XtRInt, sizeof(int),
offst(tachometer.value), XtRImmediate, (caddr_t) 0},
{XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
offst(core.height), XtRImmediate, (caddr_t) 100},
{XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
offst(core.width), XtRImmediate, (caddr_t) 100},
{XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
offst(core.border_width), XtRImmediate, (caddr_t) 0},
{XtNinternalBorderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
offst(tachometer.internal_border), XtRImmediate, (caddr_t) 0},
};
/*@ -nullderef -immediatetrans +type +nullassign @*/

static void Initialize(Widget request, Widget new),
Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes),
Resize(Widget w), Redisplay(Widget w, XEvent *event, Region region),
Destroy(Widget w);
static Boolean SetValues(Widget current, Widget request UNUSED, Widget new);

/*@ -fullinitblock @*/
TachometerClassRec tachometerClassRec = {
{
/* core_class fields */
#define superclass (&simpleClassRec)
/* superclass */ (WidgetClass) superclass,
/* class_name */ "Tachometer",
/* widget_size */ sizeof(TachometerRec),
/* class_initialize */ NULL,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ (XtInitProc) Initialize,
/* initialize_hook */ NULL,
/* realize */ Realize,
/* actions */ NULL,
/* num_actions */ 0,
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* resize */ Resize,
/* expose */ Redisplay,
/* set_values */ (XtSetValuesFunc) SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ NULL,
/* query_geometry */ NULL,
/* display_accelerator */ XtInheritDisplayAccelerator,
/* extension */ NULL
},
/* Simple class fields initialization */
{
/* change_sensitive */ XtInheritChangeSensitive
}

};
/*@ +fullinitblock @*/
WidgetClass tachometerWidgetClass = (WidgetClass)&tachometerClassRec;

/* Private procedures */

static void FastFillCircle(
Display *d, Drawable w, GC gc,
Cardinal center_x, Cardinal center_y, Cardinal radius_x, Cardinal radius_y)
{
/*@ -compdef @*/
XPoint points[360];
Cardinal angle;

for (angle = 0; angle < 360; angle++) {
points[angle].x = (short) (sin((double) angle * D2R) *
(double) radius_x + (double) center_x);
points[angle].y = (short) (cos((double) angle * D2R) *
(double) radius_y + (double) center_y);
}
(void)XFillPolygon(d, w, gc, points, 360, Complex, CoordModeOrigin);
/*@ +compdef @*/
}

static void DrawSingleNumber(TachometerWidget w, int which, Cardinal x, Cardinal y)
{
XSegment segments[7];
Cardinal nsegments, width, height, count;
width = (Cardinal)((w->core.width / 2) - w->tachometer.internal_border);
height = (Cardinal)((w->core.height / 2) - w->tachometer.internal_border);
if ((width == 0) || (height == 0))
return;

/*@ +charint -compdef */
for (count = 0, nsegments = 0; count < 7; count++)
if (num_segment[which].digit[count] == 1) {
segments[nsegments].x1 = (short)
(x + ((double)offset[count].x1 * ((double)width/200.0)));
segments[nsegments].y1 = (short)
(y + ((double)offset[count].y1 * ((double)height/200.0)));
segments[nsegments].x2 = (short)
(x + ((double)offset[count].x2 * ((double)width/200.0)));
segments[nsegments].y2 = (short)
(y + ((double)offset[count].y2 * ((double)height/200.0)));
nsegments++;
}

(void)XDrawSegments(XtDisplay(w), XtWindow(w),
w->tachometer.scale_GC, segments, (int)nsegments);
/*@ -charint +compdef */
}

static void DrawNumbers(TachometerWidget w, int which, Cardinal x, Cardinal y)
{
if (which == 10) {
DrawSingleNumber(w, 1, (Cardinal) ((double) x * 0.9), y);
DrawSingleNumber(w, 0, x, y);
} else
DrawSingleNumber(w, which, x, y);
}

static void DrawLabelString(TachometerWidget w)
{
XPoint points[5];
int char_count, data_count;
Cardinal ry, center_x, center_y, radius_x, radius_y;
GC gc;

center_x = (Cardinal)(w->core.width / 2);
center_y = (Cardinal)(w->core.height / 2);
radius_x = center_x - w->tachometer.internal_border;
radius_y = center_y - w->tachometer.internal_border;
if (!(center_x != 0 && center_y != 0 && (radius_x > 0) && (radius_y > 0)))
return;
ry = (Cardinal)(radius_y * 0.35 + center_y);
gc = w->tachometer.scale_GC;
/*@ -compdef @*/
for (char_count = 0; char_count < 4; char_count++) {
for (data_count = 0; data_count < char_data[char_count].nofline
; data_count++) {
points[data_count].x = (short)
((char_data[char_count].point_list[data_count].x) *
(double) radius_x * 0.01 + center_x);
points[data_count].y = (short)
((char_data[char_count].point_list[data_count].y) *
(double) radius_y * 0.01 + ry);
}
(void)XDrawLines(XtDisplay(w), XtWindow(w), gc, points,
char_data[char_count].nofline, CoordModeOrigin);
}
/*@ +compdef @*/
}

static void DrawGauge(TachometerWidget w)
{
XPoint points[4];
Cardinal in_gauge_x, in_gauge_y, out_gauge_x, out_gauge_y;
Cardinal number_x, number_y, center_x, center_y, radius_x, radius_y;
GC gc;
double step, jump = 1.0;

/*@ -type -unsignedcompare -compdef @*/
center_x = w->core.width / 2; center_y = w->core.height / 2;
radius_x = center_x - w->tachometer.internal_border;
radius_y = center_y - w->tachometer.internal_border;
if ((center_x==0) || (center_y==0) || (radius_x<=0) || (radius_y<=0))
return; /* Can't draw anything */

gc = w->tachometer.scale_GC;
for (step = 330.0; step >= 30.0; step -= jump) {
if ((Cardinal) (step) % 30 == 0) {
points[0].x = sin((step + 1.0)*D2R) * radius_x*0.75 + center_x;
points[0].y = cos((step + 1.0)*D2R) * radius_y*0.75 + center_y;
points[1].x = sin((step - 1.0)*D2R) * radius_x*0.75 + center_x;
points[1].y = cos((step - 1.0)*D2R) * radius_y*0.75 + center_y;
points[2].x = sin((step - 1.0)*D2R) * radius_x*0.85 + center_x;
points[2].y = cos((step - 1.0)*D2R) * radius_y*0.85 + center_y;
points[3].x = sin((step + 1.0)*D2R) * radius_x*0.85 + center_x;
points[3].y = cos((step + 1.0)*D2R) * radius_y*0.85 + center_y;
(void)XFillPolygon(XtDisplay(w), XtWindow(w), gc, points, 4,
Complex, CoordModeOrigin);

number_x = sin((step + 1.0)*D2R) * radius_x*0.65 + center_x;
number_y = cos((step + 1.0)*D2R) * radius_y*0.65 + center_y;
if ((int)((330.0 - step) / 30.0) == 1)
jump = 3.0;
DrawNumbers(w, (unsigned char) ((330.0 - step) / 30.0),
number_x, number_y);
} else {
in_gauge_x = sin(step * D2R) * radius_x * 0.8 + center_x;
in_gauge_y = cos(step * D2R) * radius_y * 0.8 + center_y;
out_gauge_x = sin(step * D2R) * radius_x * 0.85 + center_x;
out_gauge_y = cos(step * D2R) * radius_y * 0.85 + center_y;
(void)XDrawLine(XtDisplay(w), XtWindow(w), gc, in_gauge_x,
in_gauge_y, out_gauge_x, out_gauge_y);
}
}
/*@ +type +unsignedcompare +compdef @*/

DrawLabelString(w);
}

static void DrawNeedle(TachometerWidget w, int load)
{
XPoint points[6];
double cur_theta1, cur_theta2, cur_theta3, cur_theta4, cur_theta5;
Cardinal center_x, center_y, radius_x, radius_y;

/*@ -type -unsignedcompare -compdef @*/
center_x = w->core.width / 2; center_y = w->core.height / 2;
radius_x = center_x - w->tachometer.internal_border;
radius_y = center_y - w->tachometer.internal_border;
if ((center_x==0) || (center_y==0) || (radius_x<=0) || (radius_y<=0))
return; /* can't draw anything */

cur_theta1 = (double) (330 - (load * 3)) * D2R;
cur_theta2 = (double) (330 - (load * 3) + 1) * D2R;
cur_theta3 = (double) (330 - (load * 3) - 1) * D2R;
cur_theta4 = (330.0 - ((double) load * 3.0) + 7.0) * D2R;
cur_theta5 = (330.0 - ((double) load * 3.0) - 7.0) * D2R;

points[0].x = (short)(sin(cur_theta1) * radius_x * 0.75 + center_x);
points[0].y = (short)(cos(cur_theta1) * radius_y * 0.75 + center_y);
points[1].x = (short)(sin(cur_theta2) * radius_x * 0.7 + center_x);
points[1].y = (short)(cos(cur_theta2) * radius_y * 0.7 + center_y);
points[2].x = (short)(sin(cur_theta4) * radius_x * 0.1 + center_x);
points[2].y = (short)(cos(cur_theta4) * radius_y * 0.1 + center_y);
points[3].x = (short)(sin(cur_theta5) * radius_x * 0.1 + center_x);
points[3].y = (short)(cos(cur_theta5) * radius_y * 0.1 + center_y);
points[4].x = (short)(sin(cur_theta3) * radius_x * 0.7 + center_x);
points[4].y = (short)(cos(cur_theta3) * radius_y * 0.7 + center_y);
/*@ -usedef @*/
points[5].x = points[0].x;
points[5].y = points[0].y;
/*@ +usedef @*/

(void)XDrawLines(XtDisplay(w), XtWindow(w),
w->tachometer.needle_GC, points, 6, CoordModeOrigin);
/*@ +type +unsignedcompare +compdef @*/
}

static void DrawTachometer(TachometerWidget w)
{
Cardinal center_x, center_y, radius_x, radius_y;

/*@ -type -unsignedcompare -compdef @*/
center_x = w->core.width / 2; center_y = w->core.height / 2;
radius_x = center_x - w->tachometer.internal_border;
radius_y = center_y - w->tachometer.internal_border;
if ((center_x==0) || (center_y==0) || (radius_x<=0) || (radius_y<=0))
return; /* Can't draw anything -- no room */
/* Big circle */
FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.circle_GC,
center_x, center_y, radius_x, radius_y);
/* Inner circle same color as the background */
FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.background_GC,
center_x, center_y, (Cardinal) (radius_x * 0.95),
(Cardinal) (radius_y * 0.95));
/* Small circle */
FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.circle_GC,
center_x, center_y, (Cardinal) (radius_x * 0.1),
(Cardinal) (radius_y * 0.1));
/* Draw the details */
DrawGauge(w);
DrawNeedle(w, w->tachometer.value);
/*@ +type +unsignedcompare +compdef @*/
}

static void MoveNeedle(TachometerWidget w, int new)
{
int step, old, loop;

old = w->tachometer.value;
if (new > 100)
new = 100;
if (old == new)
return;
else if (old < new)
step = (w->tachometer.speed ? w->tachometer.speed : new - old);
else
step = (w->tachometer.speed ? -w->tachometer.speed : new - old);

/*@ -usedef @*/
if (old < new) {
for (loop = old; loop < new; loop += step)
DrawNeedle(w, loop);
for (loop = old + step; loop <= new; loop += step)
DrawNeedle(w, loop);
} else {
for (loop = old; loop > new; loop += step)
DrawNeedle(w, loop);
for (loop = old + step; loop >= new; loop += step)
DrawNeedle(w, loop);
}
if (loop != new + step) /* The final needle wasn't printed */
DrawNeedle(w, new);
/*@ +usedef @*/
w->tachometer.value = new;
}

static void GetneedleGC(TachometerWidget ta)
{
XGCValues values;

values.background = ta->core.background_pixel;
values.foreground = ta->tachometer.needle ^ ta->core.background_pixel;
values.function = GXxor;
/*@ -type -compdef -mustfreeonly @*/
ta->tachometer.needle_GC = XtGetGC(
(Widget)ta,
(unsigned) GCFunction | GCBackground | GCForeground,
&values);
/*@ +type +compdef +mustfreeonly @*/
}

static void GetscaleGC(TachometerWidget ta)
{
XGCValues values;

values.foreground = ta->tachometer.scale;
values.background = ta->core.background_pixel;
/*@ -type -compdef -mustfreeonly @*/
ta->tachometer.scale_GC = XtGetGC(
(Widget)ta,
(unsigned) GCForeground | GCBackground,
&values);
/*@ +type +compdef +mustfreeonly @*/
}

static void GetcircleGC(TachometerWidget ta)
{
XGCValues values;

values.foreground = ta->tachometer.circle;
values.background = ta->core.background_pixel;
/*@ -type -compdef -mustfreeonly @*/
ta->tachometer.circle_GC = XtGetGC(
(Widget)ta,
(unsigned) GCForeground | GCBackground,
&values);
/*@ +type +compdef +mustfreeonly @*/
}

static void GetbackgroundGC(TachometerWidget ta)
{
XGCValues values;

values.foreground = ta->core.background_pixel;
values.background = ta->core.background_pixel;
/*@ -type -compdef -mustfreeonly @*/
ta->tachometer.background_GC = XtGetGC(
(Widget)ta,
(unsigned) GCForeground | GCBackground,
&values);
/*@ +type +compdef +mustfreeonly @*/
}

static void Initialize(Widget request UNUSED, Widget new)
{
TachometerWidget ta = (TachometerWidget) new;
GetneedleGC(ta);
GetcircleGC(ta);
GetscaleGC(ta);
GetbackgroundGC(ta);
ta->tachometer.width = ta->tachometer.height = 0;
} /* Initialize */

static void Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
{
*valueMask |= CWBitGravity;
attributes->bit_gravity = NorthWestGravity;
(*superclass->core_class.realize) (w, valueMask, attributes);
} /* Realize */

static void Redisplay(Widget w, XEvent *event, Region region UNUSED)
{
if (event->xexpose.count == 0)
DrawTachometer((TachometerWidget) w);
} /* Redisplay */

static void Resize(Widget w)
{
TachometerWidget ta = (TachometerWidget) w;

if ((ta->core.width == ta->tachometer.width) &&
(ta->core.height == ta->tachometer.height))
/* What resize? We don't see a resize! */
return;

(void)XClearWindow(XtDisplay(w), XtWindow(w));
if ((ta->core.width <= ta->tachometer.width) &&
(ta->core.height <= ta->tachometer.height))
/* Only redraw here if no expose events are going to be */
/* generated, i.e. if the window has not grown horizontally */
/* or vertically. */
DrawTachometer(ta);

ta->tachometer.width = ta->core.width;
ta->tachometer.height = ta->core.height;
} /* Resize */

static Boolean SetValues(Widget current, Widget request UNUSED, Widget new)
/* Set specified arguments into widget */
{
/*@ -type -boolops -predboolothers @*/
Boolean back, changed = (Boolean)False;

TachometerWidget curta = (TachometerWidget) current;
TachometerWidget newta = (TachometerWidget) new;

back = (curta->core.background_pixel != newta->core.background_pixel);
if (back || (curta->tachometer.needle != newta->tachometer.needle)) {
(void)XtReleaseGC(new, newta->tachometer.needle_GC);
GetneedleGC(newta);
changed = True;
}
if (back || (curta->tachometer.scale != newta->tachometer.scale)) {
(void)XtReleaseGC(new, newta->tachometer.scale_GC);
GetscaleGC(newta);
changed = True;
}
if (back || (curta->tachometer.circle != newta->tachometer.circle)) {
(void)XtReleaseGC(new, newta->tachometer.circle_GC);
GetcircleGC(newta);
changed = True;
}
if (back) {
(void)XtReleaseGC(new, newta->tachometer.background_GC);
GetbackgroundGC(newta);
changed = True;
}
if (curta->tachometer.value != newta->tachometer.value) {
MoveNeedle(newta, newta->tachometer.value);
changed = True;
}
/*@ +type +boolops +predboolothers @*/

return(changed);
}

static void Destroy(Widget w)
{
TachometerWidget ta = (TachometerWidget) w;
(void)XtReleaseGC( w, ta->tachometer.needle_GC );
(void)XtReleaseGC( w, ta->tachometer.circle_GC );
(void)XtReleaseGC( w, ta->tachometer.scale_GC );
(void)XtReleaseGC( w, ta->tachometer.background_GC );
}

/* Exported Procedures */

int TachometerGetValue(Widget w)
{
return(((TachometerWidget) w)->tachometer.value);
}

int TachometerSetValue(Widget w, int i)
{
int old;
TachometerWidget ta = (TachometerWidget) w;

old = ta->tachometer.value;
MoveNeedle(ta, i);
return(old);
}

+ 49
- 0
Tachometer.h View File

@@ -0,0 +1,49 @@
/* $Id: Tachometer.h 3486 2006-09-21 00:58:22Z ckuethe $ */
/* Tachometer.h -- tachometer widget interface */
#ifndef _Tachometer_h
#define _Tachometer_h

#include <X11/Xaw/Simple.h>

/* Resources:

Name Class RepType Default Value
---- ----- ------- -------------
background Background Pixel XtDefaultBackground
border BorderColor Pixel XtDefaultForeground
circleColor BorderColor Pixel XtDefaultForeground
borderWidth BorderWidth Dimension 0
cursor Cursor Cursor None
destroyCallback Callback XtCallbackList NULL
foreground Foreground Pixel XtDefaultForeground
height Height Dimension 100
insensitiveBorder Insensitive Pixmap Gray
internalBorderWidth BorderWidth Dimension 0
mappedWhenManaged MappedWhenManaged Boolean True
needleColor BorderColor Pixel XtDefaultForeground
needleSpeed NeedleSpeed int 1
sensitive Sensitive Boolean True
width Width Dimension 100
value Value int 0
x Position Position 0
y Position Position 0

*/

#define XtNinternalBorderWidth "internalBorderWidth"
#define XtNtachometerNeedleSpeed "needleSpeed"
#define XtNtachometerCircleColor "circleColor"
#define XtNtachometerNeedleColor "needleColor"
#define XtCtachometerNeedleSpeed "NeedleSpeed"

extern int TachometerGetValue(Widget);
extern int TachometerSetValue(Widget, int);

/* Class record constants */

extern WidgetClass tachometerWidgetClass;

typedef struct _TachometerClassRec *TachometerWidgetClass;
typedef struct _TachometerRec *TachometerWidget;

#endif /* _Tachometer_h */

+ 41
- 0
TachometerP.h View File

@@ -0,0 +1,41 @@
/* $Id: TachometerP.h 3486 2006-09-21 00:58:22Z ckuethe $ */
/* TachometerP.h -- Tachometer widget private data */
#ifndef _TachometerP_h
#define _TachometerP_h

#include <Tachometer.h>
#include <X11/Xaw/SimpleP.h>

/* New fields for the Tachometer widget class record */
typedef struct {int foo;} TachometerClassPart;

/* Full class record declaration */
typedef struct _TachometerClassRec {
CoreClassPart core_class;
SimpleClassPart simple_class;
TachometerClassPart label_class;
} TachometerClassRec;

extern TachometerClassRec tachometerClassRec;

/* New fields for the Tachometer widget record */
typedef struct {
/* resources */
Pixel needle, scale, circle;
int value, speed;
/* private state */
GC needle_GC, scale_GC, circle_GC, background_GC;
/* We need to store the width and height separately, because when */
/* we get a resize request, we need to know if the window has */
/* gotten bigger. */
Dimension width, height, internal_border;
} TachometerPart;

/* Full instance record declaration */
typedef struct _TachometerRec {
CorePart core;
SimplePart simple;
TachometerPart tachometer;
} TachometerRec;

#endif /* _TachometerP_h */

+ 7411
- 0
aclocal.m4
File diff suppressed because it is too large
View File


+ 104
- 0
autogen.sh View File

@@ -0,0 +1,104 @@
#!/bin/sh
# $Id: autogen.sh 3486 2006-09-21 00:58:22Z ckuethe $

# Automakeversion
AM_1=1
AM_2=7
AM_3=6

# Autoconfversion
AC_1=2
AC_2=57

# Libtoolversion
LT_1=1
LT_2=5

# Check automake version
AM_VERSION=`automake --version | sed -n -e 's#[^0-9]* \([0-9]*\)\.\([0-9]*\)\.*\([0-9]*\).*$#\1 \2 \3#p'`
AM_V1=`echo $AM_VERSION | awk '{print $1}'`
AM_V2=`echo $AM_VERSION | awk '{print $2}'`
AM_V3=`echo $AM_VERSION | awk '{print $3}'`

if [ "$AM_1" -gt "$AM_V1" ]; then
AM_ERROR=1
else
if [ "$AM_1" -eq "$AM_V1" ]; then
if [ "$AM_2" -gt "$AM_V2" ]; then
AM_ERROR=1
else
if [ "$AM_2" -eq "$AM_V2" ]; then
if [ -n "$AM_V3" -o "$AM_3" -gt "$AM_V3" ]; then
AM_ERROR=1
fi
fi
fi
fi
fi

if [ "$AM_ERROR" = "1" ]; then
echo -e '\E[31;m'
echo -n "Your automake version `automake --version | sed -n -e 's#[^0-9]* \([0-9]*\.[0-9]*\.[0-9]*\).*#\1#p'`"
echo " is older than the suggested one, $AM_1.$AM_2.$AM_3"
echo "Go on at your own risk. :-)"
echo
tput sgr0
fi

# Check autoconf version
AC_VERSION=`autoconf --version | sed -n -e 's#[^0-9]* \([0-9]*\)\.\([0-9]*\).*$#\1 \2#p'`
AC_V1=`echo $AC_VERSION | awk '{print $1}'`
AC_V2=`echo $AC_VERSION | awk '{print $2}'`

if [ "$AC_1" -gt "$AC_V1" ]; then
AC_ERROR=1
else
if [ "$AC_1" -eq "$AC_V1" ]; then
if [ "$AC_2" -gt "$AC_V2" ]; then
AC_ERROR=1
fi
fi
fi

if [ "$AC_ERROR" = "1" ]; then
echo -e '\E[31;m'
echo -n "Your autoconf version `autoconf --version | sed -n -e 's#[^0-9]* \([0-9]*\.[0-9]*\).*#\1#p'`"
echo " is older than the suggested one, $AC_1.$AC_2"
echo "Go on at your own risk. :-)"
echo
tput sgr0
fi

# Check libtool version
LT_VERSION=`libtool --version | sed -n -e 's#[^0-9]* \([0-9]*\)\.\([0-9]*\).*$#\1 \2#p'`
LT_V1=`echo $LT_VERSION | awk '{print $1}'`
LT_V2=`echo $LT_VERSION | awk '{print $2}'`

if [ "$LT_1" -gt "$LT_V1" ]; then
LT_ERROR=1
else
if [ "$LT_1" -eq "$LT_V1" ]; then
if [ "$LT_2" -gt "$LT_V2" ]; then
LT_ERROR=1
fi
fi
fi

if [ "$LT_ERROR" = "1" ]; then
echo -e '\E[31;m'
echo -n "Your libtool version `libtool --version | sed -n -e 's#[^0-9]* \([0-9]*\.[0-9]*\).*#\1#p'`"
echo " is older than the suggested one, $LT_1.$LT_2"
echo "Go on at your own risk. :-)"
echo
tput sgr0
fi

echo Configuring build environment for gpsd
aclocal \
&& libtoolize --force --copy \
&& autoheader --force \
&& automake --add-missing --foreign --copy --include-deps \
&& autoconf --force \
&& echo Now running configure to configure gpsd \
&& echo "./configure $@" \
&& ./configure $@

+ 85
- 0
bits.h View File

@@ -0,0 +1,85 @@
/* $Id: bits.h 4030 2006-11-30 07:29:25Z esr $ */
/*
* bits.h - extract binary data from message buffer
*
* These macros extract bytes, words, longwords, floats or doubles from
* a message that contains these items in either MSB-first or LSB-first
* byte order. To specify which, define one of LITTLE_ENDIAN_PROTOCOL
* or BIG_ENDIAN_PROTOCOL before including this header.
*
* By defining the GET_ORIGIN and PUT_ORIGIN macros before including
* this header, it's possible to change the origin of the indexing.
*
* Assumptions:
* char is 8 bits, short is 16 bits, int is 32 bits, long long is 64 bits,
* float is 32 bits IEEE754, double is 64 bits IEEE754.
*
* The use of fixed-length types in the casts enforces these.
* Both 32- and 64-bit systems with gcc are OK with this set.
*/

#ifndef BITS_H
#define BITS_H
union int_float {
int32_t i;
float f;
};

union long_double {
int64_t l;
double d;
};
#endif /* BITS_H */

#ifndef GET_ORIGIN
#define GET_ORIGIN 0
#endif
#ifndef PUT_ORIGIN
#define PUT_ORIGIN 0
#endif

/* these are independent of byte order */
#define getsb(buf, off) ((int8_t)buf[(off)-(GET_ORIGIN)])
#define getub(buf, off) ((u_int8_t)buf[(off)-(GET_ORIGIN)])
#define putbyte(buf,off,b) do {buf[(off)-(PUT_ORIGIN)] = (unsigned char)(b);} while (0)

#ifdef LITTLE_ENDIAN_PROTOCOL

#define getsw(buf, off) ((int16_t)(((u_int16_t)getub((buf), (off)+1) << 8) | (u_int16_t)getub((buf), (off))))
#define getuw(buf, off) ((u_int16_t)(((u_int16_t)getub((buf), (off)+1) << 8) | (u_int16_t)getub((buf), (off))))
#define getsl(buf, off) ((int32_t)(((u_int16_t)getuw((buf), (off)+2) << 16) | (u_int16_t)getuw((buf), (off))))
#define getul(buf, off) ((u_int32_t)(((u_int16_t)getuw((buf),(off)+2) << 16) | (u_int16_t)getuw((buf), (off))))

#define putword(buf, off, w) do {putbyte(buf, (off)+1, (w) >> 8); putbyte(buf, (off), (w));} while (0)
#define putlong(buf, off, l) do {putword(buf, (off)+2, (l) >> 16); putword(buf, (off), (l));} while (0)
#define getsL(buf, off) ((int64_t)(((u_int64_t)getul(buf, (off)+4) << 32) | getul(buf, (off))))
#define getuL(buf, off) ((u_int64_t)(((u_int64_t)getul(buf, (off)+4) << 32) | getul(buf, (off))))

#else

/* SiRF and most other GPS protocols use big-endian (network byte order) */
#define getsw(buf, off) ((int16_t)(((u_int16_t)getub(buf, (off)) << 8) | (u_int16_t)getub(buf, (off)+1)))
#define getuw(buf, off) ((u_int16_t)(((u_int16_t)getub(buf, (off)) << 8) | (u_int16_t)getub(buf, (off)+1)))
#define getsl(buf, off) ((int32_t)(((u_int16_t)getuw(buf, (off)) << 16) | getuw(buf, (off)+2)))
#define getul(buf, off) ((u_int32_t)(((u_int16_t)getuw(buf, (off)) << 16) | getuw(buf, (off)+2)))
#define getsL(buf, off) ((int64_t)(((u_int64_t)getul(buf, (off)) << 32) | getul(buf, (off)+4)))
#define getuL(buf, off) ((u_int64_t)(((u_int64_t)getul(buf, (off)) << 32) | getul(buf, (off)+4)))

#define putword(buf,off,w) do {putbyte(buf, (off) ,(w) >> 8); putbyte(buf, (off)+1, (w));} while (0)
#define putlong(buf,off,l) do {putword(buf, (off) ,(l) >> 16); putword(buf, (off)+2, (l));} while (0)

#endif

#define getf(buf, off) (i_f.i = getsl(buf, off), i_f.f)
#define getd(buf, off) (l_d.l = getsL(buf, off), l_d.d)


/* Zodiac protocol description uses 1-origin indexing by little-endian word */
#define getword(n) ( (session->packet.outbuffer[2*(n)-2]) \
| (session->packet.outbuffer[2*(n)-1] << 8))
#define getlong(n) ( (session->packet.outbuffer[2*(n)-2]) \
| (session->packet.outbuffer[2*(n)-1] << 8) \
| (session->packet.outbuffer[2*(n)+0] << 16) \
| (session->packet.outbuffer[2*(n)+1] << 24))
#define getstring(t, s, e) \
(void)memcpy(t, session->packet.outbuffer+2*(s)-2, 2*((e)-(s)+1))

+ 124
- 0
bits_test.c View File

@@ -0,0 +1,124 @@
/* $Id: bits_test.c 3486 2006-09-21 00:58:22Z ckuethe $ */
/* test harness for bits.h */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bits.h"

/*@ -duplicatequals -formattype */
typedef unsigned long long ubig;

static unsigned char buf[80];
static union int_float i_f;
static union long_double l_d;
static char sb1,sb2;
static unsigned char ub1,ub2;
static short sw1,sw2;
static unsigned short uw1,uw2;
static int sl1,sl2;
static unsigned int ul1,ul2;
static long long sL1,sL2;
static unsigned long long uL1,uL2;
static float f1;
static double d1;

static void dumpall(void)
{
(void)printf("getsb: %016llx %016llx %016llx %016llx\n",
(ubig)sb1, (ubig)sb2,
(ubig)getsb(buf, 0), (ubig)getsb(buf, 8));
(void)printf("getub: %016llx %016llx %016llx %016llx\n",
(ubig)ub1, (ubig)ub2,
(ubig)getub(buf, 0), (ubig)getub(buf, 8));
(void)printf("getsw: %016llx %016llx %016llx %016llx\n",
(ubig)sw1, (ubig)sw2,
(ubig)getsw(buf, 0), (ubig)getsw(buf, 8));
(void)printf("getuw: %016llx %016llx %016llx %016llx\n",
(ubig)uw1, (ubig)uw2,
(ubig)getuw(buf, 0), (ubig)getuw(buf, 8));
(void)printf("getsl: %016llx %016llx %016llx %016llx\n",
(ubig)sl1, (ubig)sl2,
(ubig)getsl(buf, 0), (ubig)getsl(buf, 8));
(void)printf("getul: %016llx %016llx %016llx %016llx\n",
(ubig)ul1, (ubig)ul2,
(ubig)getul(buf, 0), (ubig)getul(buf, 8));
(void)printf("getsL: %016llx %016llx %016llx %016llx\n",
(ubig)sL1, (ubig)sL2,
(ubig)getsL(buf, 0), (ubig)getsL(buf, 8));
(void)printf("getuL: %016llx %016llx %016llx %016llx\n",
(ubig)uL1, (ubig)uL2,
(ubig)getuL(buf, 0), (ubig)getuL(buf, 8));
(void)printf("getf: %f %f\n", f1, getf(buf, 24));
(void)printf("getd: %.16f %.16f\n", d1, getd(buf, 16));
}

/*@ -duplicatequals +ignorequals @*/
int main(void)
{
memcpy(buf,"\x01\x02\x03\x04\x05\x06\x07\x08",8);
memcpy(buf+8,"\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8",8);
memcpy(buf+16,"\x40\x09\x21\xfb\x54\x44\x2d\x18",8);
memcpy(buf+24,"\x40\x49\x0f\xdb",4);

/* big-endian test */
printf("Big-endian\n");
#include "bits.h"
sb1 = getsb(buf, 0);
sb2 = getsb(buf, 8);
ub1 = getub(buf, 0);
ub2 = getub(buf, 8);
sw1 = getsw(buf, 0);
sw2 = getsw(buf, 8);
uw1 = getuw(buf, 0);
uw2 = getuw(buf, 8);
sl1 = getsl(buf, 0);
sl2 = getsl(buf, 8);
ul1 = getul(buf, 0);
ul2 = getul(buf, 8);