diff -Naur -X dontdiff clean/linux/drivers/usb/CDCEther.c linux/drivers/usb/CDCEther.c
--- clean/linux/drivers/usb/CDCEther.c	Sun Jul  8 09:16:38 2001
+++ linux/drivers/usb/CDCEther.c	Sun Jul  8 09:34:02 2001
@@ -29,7 +29,7 @@
 #include <linux/module.h>
 #include "CDCEther.h"
 
-static const char *version = __FILE__ ": v0.98.2 28 March 2001 Brad Hards and another";
+static const char *version = __FILE__ ": v0.98.4 4 July 2001 Brad Hards and another";
 
 // We will attempt to probe anything that is in the
 // communication device class...
@@ -467,7 +467,8 @@
 	// Nothing extremely useful here.
 	// We'll keep it for posterity
 	ether_dev->bcdCDC = data[0] + (data[1] << 8);
-	
+	dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
+
 	// We've seen one of these
 	*requirements &= ~REQ_HDR_FUNC_DESCR;
 	
@@ -498,14 +499,21 @@
 	// Sanity check of sorts
 	if (ether_dev->comm_interface != data[0]) {
 		// This tells us that we are chasing the wrong comm
-		// interface or we are crazy or something else wierd.
-		err( "Union Functional Descriptor tells us to use a different Communication Interface" );
-		return -1;
+		// interface or we are crazy or something else weird.
+		if (ether_dev->comm_interface == data[1]) {
+			info( "Probably broken Union descriptor, fudging data interface" );
+			// We'll need this in a few microseconds, 
+			// so guess here, and hope for the best
+			ether_dev->data_interface = data[0];
+		} else {
+			err( "Union Functional Descriptor is broken beyond repair" );
+			return -1;
+		}
+	} else{ // Descriptor is OK
+       		// We'll need this in a few microseconds!
+		ether_dev->data_interface = data[1];
 	}
-	
-	// We'll need this in a few microseconds!
-	ether_dev->data_interface = data[1];
-	
+
 	// We've seen one of these now.
 	*requirements &= ~REQ_UNION_FUNC_DESCR;
 	
@@ -587,6 +595,7 @@
 			break;
 		default:	// We don't support this at this time...
 			// However that doesn't necessarily indicate an error.
+			dbg( "Unexpected header type %x:", bDescriptorSubtype );
 			return 0;
 	}
 	// How did we get here???
@@ -627,6 +636,7 @@
 		if (rc)	{
 			// Something was hosed somewhere.
 			// No need to continue;
+			err("Bad descriptor parsing: %x", rc );
 			return -1;
 		}
 		// We have already taken three bytes.
@@ -670,7 +680,7 @@
 		// location checked above.  However I have seen it here also.
 		// This is the same device that requires the functional descriptor hack above
 		warn( "Ethernet information found at device configuration.  This is broken." );
-		rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
+		rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
 	} else 	{
 		// I don't know where else to look.
 		warn( "No ethernet information found." );
diff -Naur -X dontdiff clean/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- clean/linux/drivers/usb/usb.c	Sun Jul  8 09:16:41 2001
+++ linux/drivers/usb/usb.c	Sun Jul  8 09:38:37 2001
@@ -1217,7 +1217,7 @@
 }
 /*-------------------------------------------------------------------*/
 
-static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
+static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
 {
 	struct usb_descriptor_header *header;
 	unsigned char *begin;
@@ -1261,8 +1261,7 @@
 			return -1;
 		}
 
-		/* If we find another descriptor which is at or below us */
-		/*  in the descriptor heirarchy then we're done  */
+		/* If we find another "proper" descriptor then we're done  */
 		if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
 		    (header->bDescriptorType == USB_DT_INTERFACE) ||
 		    (header->bDescriptorType == USB_DT_CONFIG) ||
@@ -1303,7 +1302,7 @@
 	return parsed;
 }
 
-static int usb_parse_interface(struct usb_device *dev, struct usb_interface *interface, unsigned char *buffer, int size)
+static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
 {
 	int i, len, numskipped, retval, parsed = 0;
 	struct usb_descriptor_header *header;
@@ -1368,8 +1367,7 @@
 				return -1;
 			}
 
-			/* If we find another descriptor which is at or below */
-			/*  us in the descriptor heirarchy then return */
+			/* If we find another "proper" descriptor then we're done  */
 			if ((header->bDescriptorType == USB_DT_INTERFACE) ||
 			    (header->bDescriptorType == USB_DT_ENDPOINT) ||
 			    (header->bDescriptorType == USB_DT_CONFIG) ||
@@ -1435,7 +1433,7 @@
 				return -1;
 			}
 		
-			retval = usb_parse_endpoint(dev, ifp->endpoint + i, buffer, size);
+			retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
 			if (retval < 0)
 				return retval;
 
@@ -1455,7 +1453,7 @@
 	return parsed;
 }
 
-int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor *config, char *buffer)
+int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
 {
 	int i, retval, size;
 	struct usb_descriptor_header *header;
@@ -1484,6 +1482,9 @@
 	buffer += config->bLength;
 	size -= config->bLength;
 	
+	config->extra = NULL;
+	config->extralen = 0;
+
 	for (i = 0; i < config->bNumInterfaces; i++) {
 		int numskipped, len;
 		char *begin;
@@ -1500,8 +1501,7 @@
 				return -1;
 			}
 
-			/* If we find another descriptor which is at or below */
-			/*  us in the descriptor heirarchy then we're done  */
+			/* If we find another "proper" descriptor then we're done  */
 			if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
 			    (header->bDescriptorType == USB_DT_INTERFACE) ||
 			    (header->bDescriptorType == USB_DT_CONFIG) ||
@@ -1520,22 +1520,23 @@
 		/* Copy any unknown descriptors into a storage area for */
 		/*  drivers to later parse */
 		len = (int)(buffer - begin);
-		if (!len) {
-			config->extra = NULL;
-			config->extralen = 0;
-		} else {
-			config->extra = kmalloc(len, GFP_KERNEL);
-			if (!config->extra) {
-				err("couldn't allocate memory for config extra descriptors");
-				config->extralen = 0;
-				return -1;
-			}
+		if (len) {
+			if (config->extralen) {
+				warn("extra config descriptor");
+			} else {
+				config->extra = kmalloc(len, GFP_KERNEL);
+				if (!config->extra) {
+					err("couldn't allocate memory for config extra descriptors");
+					config->extralen = 0;
+					return -1;
+				}
 
-			memcpy(config->extra, begin, len);
-			config->extralen = len;
+				memcpy(config->extra, begin, len);
+				config->extralen = len;
+			}
 		}
 
-		retval = usb_parse_interface(dev, config->interface + i, buffer, size);
+		retval = usb_parse_interface(config->interface + i, buffer, size);
 		if (retval < 0)
 			return retval;
 
@@ -2079,7 +2080,7 @@
 
 		dev->rawdescriptors[cfgno] = bigbuffer;
 
-		result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer);
+		result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
 		if (result > 0)
 			dbg("descriptor data left");
 		else if (result < 0) {
