diff -u usbutils-0.7/configure usbutils/configure
--- usbutils-0.7/configure	Fri Nov  3 08:51:23 2000
+++ usbutils/configure	Mon Feb  5 14:01:30 2001
@@ -781,7 +781,7 @@
 
 PACKAGE=usbutils
 
-VERSION=0.7
+VERSION=0.7hotplug
 
 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
   { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
diff -u usbutils-0.7/usbmodules.8 usbutils/usbmodules.8
--- usbutils-0.7/usbmodules.8	Fri Nov  3 07:30:51 2000
+++ usbutils/usbmodules.8	Mon Feb  5 13:59:06 2001
@@ -1,19 +1,24 @@
-.TH usbmodules 8 "03 November 2000" "usbutils-0.6" "Linux USB Utilities"
+.TH usbmodules 8 "05 February 2001" "usbutils-0.7hotplug" "Linux USB Utilities"
 .IX usbmodules
 .SH NAME
-usbmodules \- List kernel driver modules available for all currently plugged
-in USB devices
+usbmodules \- List kernel driver modules available for a plugged
+in USB device
 .SH SYNOPSIS
 .B usbmodules
-.RB [ --device /proc/bus/bus/NNN/NNN ]
-.RB [ --check modulename ]
+.RB [ "--device " /proc/bus/bus/NNN/NNN ]
+.RB [ "--check " modulename ]
 .RB [ --help ]
+.RB [ "--mapfile " pathname ]
+.RB [ "--version " pathname ]
 .SH DESCRIPTION
 .B usbmodules
-lists all driver modules for all currently plugged in USB devices.
-.B usbmodules
-should be run at by /sbin/hotplug of /etc/usb/policy, and whenever
-a USB device is "hot plugged" into the system.  This can be done by
+lists driver modules that may be
+able to manage interfaces on
+currently plugged in USB devices.
+.B usbmodules
+may be used by /sbin/hotplug or one of its agents (normally
+.IR /etc/hotplug/usb.agent )
+when USB devices are "hot plugged" into the system.  This can be done by
 the following Bourne shell syntax:
 .IP
 	for module in $(usbmodules --device $DEVICE) ; do
@@ -22,7 +27,11 @@
 .IP
 	done
 .PP
-The DEVICE environment variable is passed from the kernel to /sbin/hotplug.
+The DEVICE environment variable is passed from the kernel to /sbin/hotplug
+during USB hotplugging if the kernel was configured using
+.I usbdevfs.
+.B usbmodules
+currently requires usbdevfs to operate.
 .PP
 When a USB device is removed from the system, the Linux kernel will
 decrement a usage count on USB driver module.  If this count drops
@@ -33,38 +42,52 @@
 .PP
 .SH OPTIONS
 .TP
-.B --check modulename
+.BI "--check " modulename
 Instead of listing the relevant modules, just exit with code 0 (success)
 if the given module's exported USB ID patterns matches.  Otherwise,
 return failure.  
 .B usbmodules
 emits no output either way.
 .TP
-.B --device /proc/bus/usb/NNN/NNN
+.BI "--device " /proc/bus/usb/MMM/NNN
 Selects which device
 .B usbmodules
 will examine.  The argument is currently mandatory.
 .TP
 .B --help, -h
 Print a help message
-.SH FILES
 .TP
+.BI "--mapfile " /etc/hotplug/usb.handmap
+Use the specified file instead of the
+/lib/modules/.../modules.usbmap file
+corresponding to the running kernel.
+.TP
+.B --version
+Identifies the version of
+.I usbutils
+this tool was built with.
 .SH FILES
+.TP
 .B /lib/modules/<kernel-version>/modules.usbmap
 This file is automatically generated by
 .B depmod,
-and used by
+versions 2.4.2 and later, and is used by
 .B usbmodules
 to determine which modules correspond to which USB ID's.
 .TP
 .B /proc/bus/usb
-An interface to USB bus configuration space provided by the post-2.1.82 Linux
-kernels. Contains per-bus subdirectories with per-card config space files and a
+An optional interface to USB devices provided by Linux kernels with
+versions of the 2.4 USB support. Contains per-bus subdirectories
+with per-device files (offering a usermode driver API as well
+as access to device and configuration descriptors), a
 .I devices
-file containing a list of all USB devices.
+file containing a list of all USB devices, and a 
+.I drivers
+file listing USB device drivers known to the USB subsystem.
 
 .SH SEE ALSO
-.BR lsusb (8)
+.BR lsusb (8),
+.I http://linux-hotplug.sourceforge.net
 
 .SH AUTHOR
 .B usbmodules
@@ -73,6 +96,8 @@
 .B
 lsusb,
 which was written by Thomas Sailer <sailer@ife.ee.ethz.ch>.
+
+.\" Code and documentation updated by David Brownell.
 
 
 .SH COPYRIGHT
diff -u usbutils-0.7/usbmodules.c usbutils/usbmodules.c
--- usbutils-0.7/usbmodules.c	Fri Nov  3 07:30:52 2000
+++ usbutils/usbmodules.c	Mon Feb  5 13:04:05 2001
@@ -3,13 +3,17 @@
 /*
  *      usmodules.c  --  pcimodules like utility for the USB bus
  *     
- *      Written by primarily by Adam J. Richter.  lspci.c is derived from:
- *      lsusb.c, written by Thomas Sailer, and pcimodules.c, which is
- *      also written by Adam J. Richter.  usbmodules.h is derived from
- *      linux-2.4.0-test10/include/linux/usb.h (exact authorship unknown,
- *      probably Randy Dunlap).
+ *	lsusb.c is derived from:
  *
- *      Copyright (C) 2000  Yggdrasil Computing, Inc.
+ *	lspci.c					by Thomas Sailer,
+ *	pcimodules.c				by Adam J. Richter
+ *	linux-2.4.0-test10/include/linux/usb.h	probably by Randy Dunlap
+ *
+ *	The code in usbmodules not derived from elsewhere was written by
+ *	Adam J. Richter.  David Brownell added the --mapfile and --version
+ *	options.
+ *
+ *	Copyright (C) 2000, 2001  Yggdrasil Computing, Inc.
  *      Copyright (C) 1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      This program is free software; you can redistribute it and/or modify
@@ -68,12 +72,14 @@
 #define _GNU_SOURCE
 #include <getopt.h>
 
-#define OPT_STRING "c:d:h"
+#define OPT_STRING "c:d:hm:v"
 static struct option long_options[] = {
 	{"check",	required_argument,	NULL,	'c'},
-       {"device",      required_argument,      NULL,   'd'},
+	{"device",      required_argument,      NULL,   'd'},
 	{"help",	no_argument, 		NULL,	'h'},
-       { 0,            0,                      NULL,   0}
+	{"mapfile",     required_argument,      NULL,   'm'},
+	{"version",	no_argument, 		NULL,	'v'},
+	{ 0,            0,                      NULL,   0}
 };
 
 #define MODDIR "/lib/modules"
@@ -92,8 +98,6 @@
 
 static char *checkname = NULL;
 
-static const char *procbususb = "/proc/bus/usb";
-
 static int idVendor;
 static int idProduct;
 static int bcdDevice;
@@ -109,27 +113,103 @@
                fprintf(stderr, "Memory allocation failure.\n");
                exit(1);
        }
+       return result;
+}
+
+static int
+scan_without_flags(const char *line, struct usbmap_entry *entry, char *name) {
+	unsigned int driver_info;
+	if (sscanf(line,
+		   "%s 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+		   name,
+		   &entry->idVendor,
+		   &entry->idProduct,
+		   &entry->bcdDevice_lo,
+		   &entry->bcdDevice_hi,
+		   &entry->bDeviceClass,
+		   &entry->bDeviceSubClass,
+		   &entry->bDeviceProtocol,
+		   &entry->bInterfaceClass,
+		   &entry->bInterfaceSubClass,
+		   &entry->bInterfaceProtocol,
+		   &driver_info) != 12)
+		return 0;
+
+	entry->match_flags = 0;
+
+	/* idVendor==0 is the wildcard for both idVendor and idProduct,
+	   because idProduct==0 is a legitimate product ID. */
+	if (entry->idVendor)
+		entry->match_flags |= USB_MATCH_VENDOR | USB_MATCH_PRODUCT;
+
+	if (entry->bcdDevice_lo)
+		entry->match_flags |= USB_MATCH_DEV_LO;
+
+	if (entry->bcdDevice_hi)
+		entry->match_flags |= USB_MATCH_DEV_HI;
+
+	if (entry->bDeviceClass)
+		entry->match_flags |= USB_MATCH_DEV_CLASS;
+
+	if (entry->bDeviceSubClass)
+		entry->match_flags |= USB_MATCH_DEV_SUBCLASS;
+
+	if (entry->bDeviceProtocol)
+		entry->match_flags |= USB_MATCH_DEV_PROTOCOL;
+
+	if (entry->bInterfaceClass)
+		entry->match_flags |= USB_MATCH_INT_CLASS;
+
+	if (entry->bInterfaceSubClass)
+		entry->match_flags |= USB_MATCH_INT_SUBCLASS;
+
+	if (entry->bInterfaceProtocol)
+		entry->match_flags |= USB_MATCH_INT_PROTOCOL;
+
+	return 1;
+}
+
+static int
+scan_with_flags(const char *line, struct usbmap_entry *entry, char *name) {
+	unsigned int driver_info;
+	return (sscanf(line, "%s 0x%x 0x%x "
+		       "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+		       name,
+		       &entry->match_flags,
+		       &entry->idVendor,
+		       &entry->idProduct,
+		       &entry->bcdDevice_lo,
+		       &entry->bcdDevice_hi,
+		       &entry->bDeviceClass,
+		       &entry->bDeviceSubClass,
+		       &entry->bDeviceProtocol,
+		       &entry->bInterfaceClass,
+		       &entry->bInterfaceSubClass,
+		       &entry->bInterfaceProtocol,
+		       &driver_info) == 13);
 }
 
 void
-read_modules_usbmap(void)
+read_modules_usbmap(char *pathname)
 {
-       struct utsname utsname;
        char filename[MAXPATHLEN];
        FILE *usbmap_file;
        char line[LINELENGTH];
        struct usbmap_entry *prev;
        struct usbmap_entry *entry;
-       unsigned int driver_data;
        char name[LINELENGTH];
 
-       if (uname(&utsname) < 0) {
-               perror("uname");
-               exit(1);
+       if (pathname == NULL) {
+	       struct utsname utsname;
+	       if (uname(&utsname) < 0) {
+		       perror("uname");
+		       exit(1);
+	       }
+	       sprintf(filename, "%s/%s/%s", MODDIR, utsname.release, USBMAP);
+	       pathname = filename;
        }
-       sprintf(filename, "%s/%s/%s", MODDIR, utsname.release, USBMAP);
-       if ((usbmap_file = fopen(filename, "r")) == NULL) {
-               perror(filename);
+       if ((usbmap_file = fopen(pathname, "r")) == NULL) {
+               perror(pathname);
                exit(1);
        }
 
@@ -140,18 +220,8 @@
 
                entry = xmalloc(sizeof(struct usbmap_entry));
 
-               if (sscanf(line, "%s 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
-                          name,
-                          &entry->idVendor,
-                          &entry->idProduct,
-                          &entry->bcdDevice_lo,
-                          &entry->bcdDevice_hi,
-                          &entry->bDeviceClass,
-                          &entry->bDeviceSubClass,
-                          &entry->bDeviceProtocol,
-                          &entry->bInterfaceClass,
-                          &entry->bInterfaceSubClass,
-                          &entry->bInterfaceProtocol) != 10) {
+	       if (!scan_with_flags(line, entry, name) &&
+		   !scan_without_flags(line, entry, name)) {
                        fprintf (stderr,
                                "modules.usbmap unparsable line: %s.\n", line);
                        free(entry);
@@ -195,45 +265,44 @@
 
        for (mod = usbmap_list; mod != NULL; mod = mod->next) {
 
-               if (mod->idVendor &&
+	       if ((mod->match_flags & USB_MATCH_VENDOR) &&
                    mod->idVendor != idVendor)
                        continue;
 
-               if (mod->idProduct &&
+	       if ((mod->match_flags & USB_MATCH_PRODUCT) &&
                    mod->idProduct != idProduct)
                        continue;
 
-               /* No need to test mod->bcdDevice_lo != 0, since 0 is never
-                  greater than any unsigned number. */
-               if (mod->bcdDevice_lo > bcdDevice)
+	       if ((mod->match_flags & USB_MATCH_DEV_LO) &&
+		   mod->bcdDevice_lo > bcdDevice)
                        continue;
 
-               if (mod->bcdDevice_hi &&
+	       if ((mod->match_flags & USB_MATCH_DEV_HI) &&
                    mod->bcdDevice_hi < bcdDevice)
                        continue;
 
-               if (mod->bDeviceClass &&
+	       if ((mod->match_flags & USB_MATCH_DEV_CLASS) &&
                    mod->bDeviceClass != bDeviceClass)
                        continue;
 
-               if (mod->bDeviceSubClass &&
-                   mod->bDeviceSubClass!= bDeviceClass)
+	       if ((mod->match_flags & USB_MATCH_DEV_SUBCLASS) &&
+		   mod->bDeviceSubClass != bDeviceSubClass)
                        continue;
 
-               if (mod->bDeviceProtocol &&
+	       if ((mod->match_flags & USB_MATCH_DEV_PROTOCOL) &&
                    mod->bDeviceProtocol != bDeviceProtocol)
                        continue;
 
-               if (mod->bInterfaceClass
-                   && mod->bInterfaceClass != bInterfaceClass)
+	       if ((mod->match_flags & USB_MATCH_INT_CLASS) &&
+		   mod->bInterfaceClass != bInterfaceClass)
                        continue;
 
-               if (mod->bInterfaceSubClass &&
+	       if ((mod->match_flags & USB_MATCH_INT_SUBCLASS) &&
                    mod->bInterfaceSubClass != bInterfaceSubClass)
                    continue;
 
-               if (mod->bInterfaceProtocol
-                   && mod->bInterfaceProtocol != bInterfaceProtocol)
+	       if ((mod->match_flags & USB_MATCH_INT_PROTOCOL) &&
+		   mod->bInterfaceProtocol != bInterfaceProtocol)
                    continue;
 
 		if (checkname != NULL) {
@@ -286,9 +355,6 @@
 {
        unsigned char buf[1024], *p;
        unsigned int sz;
-       int bInterfaceClass;
-       int bInterfaceSubClass;
-       int bInterfaceProtocol;
 
        if (usb_control_msg(fd, USB_DIR_IN, USB_REQ_GET_DESCRIPTOR,
                            (USB_DT_CONFIG << 8) | nr,
@@ -327,8 +393,6 @@
 static void process_device(const char *path)
 {
         unsigned char buf[USB_DT_DEVICE_SIZE];
-       unsigned int vid, pid;
-       char vendor[128], product[128];
         int fd;
        unsigned int i, maxcfg;
 
@@ -367,6 +431,7 @@
        int opt_index = 0;
        int opt;
        char *device = NULL;
+       char *pathname = NULL;
 
        while ((opt = getopt_long(argc, argv, OPT_STRING, long_options,
                           &opt_index)) != -1) {
@@ -378,10 +443,17 @@
                                device = optarg;
                                break;
                        case 'h':
-				printf ("Usage: usbmodules [--help] [--device //proc/bus/usb/NNN/NNN] [--check module]\n"
+				printf ("Usage: usbmodules [--help] [--device /proc/bus/usb/NNN/NNN] [--check module]\n"
+				"\t[--mapfile pathname] [--version]\n"
 	"  Lists kernel modules corresponding to USB devices currently plugged\n"
                                        "  into the computer.\n");
                                return 0;
+		       case 'm':
+                               pathname = optarg;
+                               break;
+		       case 'v':
+                               puts (VERSION);
+                               return 0;
                        default:
                                fprintf(stderr,
                                        "Unknown argument character \"%c\".\n",
@@ -396,7 +468,7 @@
                         "\tusbmodules --device /proc/bus/usb/001/009\n");
                return 1;
        }
-       read_modules_usbmap();
+       read_modules_usbmap(pathname);
        process_device(device);
 
 	if (checkname != NULL)
diff -u usbutils-0.7/usbmodules.h usbutils/usbmodules.h
--- usbutils-0.7/usbmodules.h	Fri Nov  3 06:00:32 2000
+++ usbutils/usbmodules.h	Mon Feb  5 12:54:16 2001
@@ -1,7 +1,19 @@
 /* Declaring the usb_device_id fields as unsigned int simplifies
    the sscanf call. */
 
+#define USB_MATCH_VENDOR		0x0001
+#define USB_MATCH_PRODUCT		0x0002
+#define USB_MATCH_DEV_LO		0x0004
+#define USB_MATCH_DEV_HI		0x0008
+#define USB_MATCH_DEV_CLASS		0x0010
+#define USB_MATCH_DEV_SUBCLASS		0x0020
+#define USB_MATCH_DEV_PROTOCOL		0x0040
+#define USB_MATCH_INT_CLASS		0x0080
+#define USB_MATCH_INT_SUBCLASS		0x0100
+#define USB_MATCH_INT_PROTOCOL		0x0200
+
 struct usbmap_entry {
+	unsigned int		match_flags;
 	/*
 	 * vendor/product codes are checked, if vendor is nonzero
 	 * Range is for device revision (bcdDevice), inclusive;
