diff options
-rw-r--r-- | INSTALL | 6 | ||||
-rw-r--r-- | Makefile.am | 16 | ||||
-rw-r--r-- | driver_garmin.c | 70 | ||||
-rw-r--r-- | www/hacking.html | 16 |
4 files changed, 83 insertions, 25 deletions
@@ -20,6 +20,7 @@ pthreads library -> support for PPS timekeeping on serial GPSes DBUS -> gpsd will issue DBUS notifications X windows -> two test clients depend on this ncurses -> two more test clients depend on this +libusb-1.0.x or later -> better USB device discovery Qt + qmake -> libQgpsmm depends on this Python 2.6 or 2.4+ & simplejson. The Python code in GPSD is @@ -28,6 +29,11 @@ from 2.6 or the functionally equivalent simplejson backport. Note that while Python is required to *build* GPSD (the build uses some code generators in Python), it is not required to *run* GPSD. +If you have libusb-1.0.0 or later, the GPSD build will autodetect +this and use it to discover Garmin USB GPSes, rather than groveling +through /proc/bus/usb/devices (which has been deprecated by the +Linux kernel team). + For building from the source tree, the following are necessary: autoconf 2.61 or later automake 1.10 or later diff --git a/Makefile.am b/Makefile.am index 84648c37..deb32703 100644 --- a/Makefile.am +++ b/Makefile.am @@ -84,19 +84,19 @@ xgpsspeed_c_sources = \ xgpsspeed_SOURCES = \ $(xgpsspeed_c_sources) \ xgpsspeed.icon -xgpsspeed_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(XAW_LIBS) $(XT_LIBS) $(X_LIBS) $(X_PRE_LIBS) libgps.la -lm $(LIBPTHREAD) +xgpsspeed_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(XAW_LIBS) $(XT_LIBS) $(X_LIBS) $(X_PRE_LIBS) libgps.la -lm $(LIBPTHREAD) $(LIBUSB) # # Build cgps # cgps_SOURCES = cgps.c -cgps_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(NCURSES_LIBS) libgps.la -lm $(LIBPTHREAD) +cgps_LDADD = $(LIBM) $(LIBC) $(LIBNSL) $(LIBSOCKET) $(NCURSES_LIBS) libgps.la -lm $(LIBPTHREAD) $(LIBUSB) # # Build gpxlogger # gpxlogger_SOURCES = gpxlogger.c -gpxlogger_LDADD = $(DBUS_GLIB_LIBS) libgps.la -lm +gpxlogger_LDADD = $(DBUS_GLIB_LIBS) libgps.la -lm $(LIBUSB) # # Build gpsd @@ -109,19 +109,19 @@ gpsd_LDADD = $(DBUS_LIBS) $(LIBM) libgps.la -lm $(LIBPTHREAD) $(LIBUSB) # Build gpsctl # gpsctl_SOURCES = gpsctl.c -gpsctl_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD) +gpsctl_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD) $(LIBUSB) # # Build gpspipe # gpspipe_SOURCES = gpspipe.c -gpspipe_LDADD = $(DBUS_LIBS) $(LIBM) libgps.la -lm +gpspipe_LDADD = $(DBUS_LIBS) $(LIBM) libgps.la -lm $(LIBUSB) # # Build lcdgps # lcdgps_SOURCES = lcdgps.c -lcdgps_LDADD = $(LIBM) libgps.la -lm +lcdgps_LDADD = $(LIBM) libgps.la -lm $(LIBUSB) # # Build gpsmon @@ -129,13 +129,13 @@ lcdgps_LDADD = $(LIBM) libgps.la -lm gpsmon_SOURCES = gpsmon.c monitor_nmea.c monitor_sirf.c \ monitor_italk.c monitor_ubx.c monitor_superstar2.c \ monitor_oncore.c monitor_tnt.c -gpsmon_LDADD = $(LIBM) $(NCURSES_LIBS) libgps.la -lm $(LIBPTHREAD) +gpsmon_LDADD = $(LIBM) $(NCURSES_LIBS) libgps.la -lm $(LIBPTHREAD) $(LIBUSB) # # Build gpsdecode # gpsdecode_SOURCES = gpsdecode.c -gpsdecode_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD) +gpsdecode_LDADD = $(LIBM) libgps.la -lm $(LIBPTHREAD) $(LIBUSB) # # Build shared libraries diff --git a/driver_garmin.c b/driver_garmin.c index b53d61e9..b41f1f8d 100644 --- a/driver_garmin.c +++ b/driver_garmin.c @@ -101,6 +101,10 @@ #include <strings.h> #endif +#if defined(HAVE_LIBUSB) +#include <libusb.h> +#endif + #include "gpsd.h" #include "gps.h" @@ -799,6 +803,65 @@ static void Build_Send_SER_Packet(struct gps_device_t *session, } +#if defined(__linux__) || defined(S_SPLINT_S) +/* + * is_usb_device() - is a specified device USB matching given vendor/product? + * + * BUG: Doesn't actually match against path yet. Must finish this function + * by querying /sys/dev/char, either directly or using libudev. Greg KH + * assures this is possible, though he is vague about how. + * + * libudev: http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/ + */ +static bool is_usb_device(const char *path UNUSED, int vendor, int product) +{ + // discover devices + libusb_device **list; + ssize_t cnt; + ssize_t i = 0; + bool found = false; + + gpsd_report(LOG_SHOUT, "attempting USB device enumeration.\n"); + libusb_init(NULL); + + if ((cnt = libusb_get_device_list(NULL, &list)) < 0) { + gpsd_report(LOG_ERROR, "USB device list call failed.\n"); + libusb_exit(NULL); + return false; + } + + for (i = 0; i < cnt; i++) { + struct libusb_device_descriptor desc; + libusb_device *dev = list[i]; + + int r = libusb_get_device_descriptor(dev, &desc); + if (r < 0) { + gpsd_report(LOG_ERROR, + "USB descriptor fetch failed on device %zd.\n", + i); + continue; + } + + /* we can extract device descriptor data */ + gpsd_report(LOG_SHOUT, "%04x:%04x (bus %d, device %d)\n", + desc.idVendor, desc.idProduct, + libusb_get_bus_number(dev), + libusb_get_device_address(dev)); + + /* we match if vendor and product ID are right */ + if (desc.idVendor == 0x91e && desc.idProduct == 3) { + found = true; + break; + } + } + + gpsd_report(LOG_SHOUT, "vendor/product match with %04x:%04x %sfound\n", + vendor, product, found ? "" : "not "); + libusb_free_device_list(list, 1); + libusb_exit(NULL); + return found; +} +#endif /* __linux__ || S_SPLINT_S */ /* * garmin_usb_detect() - detect a Garmin USB device connected to ession fd. @@ -837,6 +900,10 @@ static bool garmin_usb_detect(struct gps_device_t *session) if (session->sourcetype != source_usb) return false; else { +#ifdef HAVE_LIBUSB + if (!is_usb_device(session->gpsdata.dev.path, 0x091e, 0x0003)) + return false; +#else /* * This is ONLY for USB devices reporting as: 091e:0003. * @@ -883,6 +950,7 @@ static bool garmin_usb_detect(struct gps_device_t *session) gpsd_report(LOG_WARN, "Garmin: Can't open /proc/bus/usb/devices, will try anyway\n"); } +#endif /* HAVE_LIBUSB */ if (!gpsd_set_raw(session)) { gpsd_report(LOG_ERROR, @@ -920,7 +988,7 @@ static bool garmin_usb_detect(struct gps_device_t *session) } #else return false; -#endif /* __linux__ */ +#endif /* __linux__ || S_SPLINT_S */ } static void garmin_event_hook(struct gps_device_t *session, event_t event) diff --git a/www/hacking.html b/www/hacking.html index 0771b674..afeffb2b 100644 --- a/www/hacking.html +++ b/www/hacking.html @@ -1176,22 +1176,6 @@ daemon running — but a bad idea. It would make denial-of-service attacks on applications using the GPS far too easy. For example, suppose the control string were a baud-rate change?</p> -<h2 id="libusb">Using libusb to do USB device discovery</h2> - -<p>There has been some consideration of going to the cross-platform libusb -library to do USB device discovery. This would create an external -dependency that gpsd doesn't now have, and bring more complexity on -board than is probably desirable.</p> - -<p>We've chosen instead to rely on the local hotplug system. That way -gpsd can concentrate solely on knowing about GPSes.</p> - -<p>There has been talk of revisiting libusb as a more reliable way to -communicate with Garmin receivers. By implementing the driver in user -space with libusb, we gain portability and freedom from buggy kernel -modules. It may also offer us a way to better support OS X. It's not a -dead issue any more.<p> - <h2 id="fifo">Setting FIFO threshold to 1 to reduce jitter in serial-message times</h2> <p>When using gpsd as a time reference, one of the things we'd like to do |