summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL6
-rw-r--r--Makefile.am16
-rw-r--r--driver_garmin.c70
-rw-r--r--www/hacking.html16
4 files changed, 83 insertions, 25 deletions
diff --git a/INSTALL b/INSTALL
index af031ce3..82c7f423 100644
--- a/INSTALL
+++ b/INSTALL
@@ -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 &mdash; 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