# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.613   -> 1.614  
#	drivers/usb/core/usb.c	1.62    -> 1.63   
#	drivers/usb/core/Makefile	1.6     -> 1.7    
#	               (new)	        -> 1.2     drivers/usb/core/config.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/05/30	mochel@osdl.org	1.614
# USB: Move configuration parsing code from usb.c to config.c
# --------------------------------------------
#
diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
--- a/drivers/usb/core/Makefile	Fri May 31 16:47:03 2002
+++ b/drivers/usb/core/Makefile	Fri May 31 16:47:03 2002
@@ -2,9 +2,10 @@
 # Makefile for USB Core files and filesystem
 #
 
-export-objs	:= usb.o hcd.o urb.o message.o 
+export-objs	:= usb.o hcd.o urb.o message.o config.o
 
-usbcore-objs	:= usb.o usb-debug.o hub.o hcd.o urb.o message.o 
+usbcore-objs	:= usb.o usb-debug.o hub.o hcd.o urb.o message.o \
+			config.o
 
 ifeq ($(CONFIG_USB_DEVICEFS),y)
 	usbcore-objs	+= devio.o inode.o drivers.o devices.o
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/config.c	Fri May 31 16:47:03 2002
@@ -0,0 +1,494 @@
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
+{
+	struct usb_descriptor_header *header;
+	unsigned char *begin;
+	int parsed = 0, len, numskipped;
+
+	header = (struct usb_descriptor_header *)buffer;
+
+	/* Everything should be fine being passed into here, but we sanity */
+	/*  check JIC */
+	if (header->bLength > size) {
+		err("ran out of descriptors parsing");
+		return -1;
+	}
+		
+	if (header->bDescriptorType != USB_DT_ENDPOINT) {
+		warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
+			endpoint->bDescriptorType, USB_DT_ENDPOINT);
+		return parsed;
+	}
+
+	if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
+		memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
+	else
+		memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
+	
+	le16_to_cpus(&endpoint->wMaxPacketSize);
+
+	buffer += header->bLength;
+	size -= header->bLength;
+	parsed += header->bLength;
+
+	/* Skip over the rest of the Class Specific or Vendor Specific */
+	/*  descriptors */
+	begin = buffer;
+	numskipped = 0;
+	while (size >= sizeof(struct usb_descriptor_header)) {
+		header = (struct usb_descriptor_header *)buffer;
+
+		if (header->bLength < 2) {
+			err("invalid descriptor length of %d", header->bLength);
+			return -1;
+		}
+
+		/* 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) ||
+		    (header->bDescriptorType == USB_DT_DEVICE))
+			break;
+
+		dbg("skipping descriptor 0x%X",
+			header->bDescriptorType);
+		numskipped++;
+
+		buffer += header->bLength;
+		size -= header->bLength;
+		parsed += header->bLength;
+	}
+	if (numskipped)
+		dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
+
+	/* Copy any unknown descriptors into a storage area for drivers */
+	/*  to later parse */
+	len = (int)(buffer - begin);
+	if (!len) {
+		endpoint->extra = NULL;
+		endpoint->extralen = 0;
+		return parsed;
+	}
+
+	endpoint->extra = kmalloc(len, GFP_KERNEL);
+
+	if (!endpoint->extra) {
+		err("couldn't allocate memory for endpoint extra descriptors");
+		endpoint->extralen = 0;
+		return parsed;
+	}
+
+	memcpy(endpoint->extra, begin, len);
+	endpoint->extralen = len;
+
+	return parsed;
+}
+
+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;
+	struct usb_interface_descriptor *ifp;
+	unsigned char *begin;
+
+	interface->act_altsetting = 0;
+	interface->num_altsetting = 0;
+	interface->max_altsetting = USB_ALTSETTINGALLOC;
+
+	interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
+	
+	if (!interface->altsetting) {
+		err("couldn't kmalloc interface->altsetting");
+		return -1;
+	}
+
+	while (size > 0) {
+		if (interface->num_altsetting >= interface->max_altsetting) {
+			void *ptr;
+			int oldmas;
+
+			oldmas = interface->max_altsetting;
+			interface->max_altsetting += USB_ALTSETTINGALLOC;
+			if (interface->max_altsetting > USB_MAXALTSETTING) {
+				warn("too many alternate settings (max %d)",
+					USB_MAXALTSETTING);
+				return -1;
+			}
+
+			ptr = interface->altsetting;
+			interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
+			if (!interface->altsetting) {
+				err("couldn't kmalloc interface->altsetting");
+				interface->altsetting = ptr;
+				return -1;
+			}
+			memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas);
+
+			kfree(ptr);
+		}
+
+		ifp = interface->altsetting + interface->num_altsetting;
+		ifp->endpoint = NULL;
+		ifp->extra = NULL;
+		ifp->extralen = 0;
+		interface->num_altsetting++;
+
+		memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
+
+		/* Skip over the interface */
+		buffer += ifp->bLength;
+		parsed += ifp->bLength;
+		size -= ifp->bLength;
+
+		begin = buffer;
+		numskipped = 0;
+
+		/* Skip over any interface, class or vendor descriptors */
+		while (size >= sizeof(struct usb_descriptor_header)) {
+			header = (struct usb_descriptor_header *)buffer;
+
+			if (header->bLength < 2) {
+				err("invalid descriptor length of %d", header->bLength);
+				return -1;
+			}
+
+			/* 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) ||
+			    (header->bDescriptorType == USB_DT_DEVICE))
+				break;
+
+			numskipped++;
+
+			buffer += header->bLength;
+			parsed += header->bLength;
+			size -= header->bLength;
+		}
+
+		if (numskipped)
+			dbg("skipped %d class/vendor specific interface descriptors", numskipped);
+
+		/* Copy any unknown descriptors into a storage area for */
+		/*  drivers to later parse */
+		len = (int)(buffer - begin);
+		if (len) {
+			ifp->extra = kmalloc(len, GFP_KERNEL);
+
+			if (!ifp->extra) {
+				err("couldn't allocate memory for interface extra descriptors");
+				ifp->extralen = 0;
+				return -1;
+			}
+			memcpy(ifp->extra, begin, len);
+			ifp->extralen = len;
+		}
+
+		/* Did we hit an unexpected descriptor? */
+		header = (struct usb_descriptor_header *)buffer;
+		if ((size >= sizeof(struct usb_descriptor_header)) &&
+		    ((header->bDescriptorType == USB_DT_CONFIG) ||
+		     (header->bDescriptorType == USB_DT_DEVICE)))
+			return parsed;
+
+		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
+			warn("too many endpoints");
+			return -1;
+		}
+
+		ifp->endpoint = (struct usb_endpoint_descriptor *)
+			kmalloc(ifp->bNumEndpoints *
+			sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
+		if (!ifp->endpoint) {
+			err("out of memory");
+			return -1;	
+		}
+
+		memset(ifp->endpoint, 0, ifp->bNumEndpoints *
+			sizeof(struct usb_endpoint_descriptor));
+	
+		for (i = 0; i < ifp->bNumEndpoints; i++) {
+			header = (struct usb_descriptor_header *)buffer;
+
+			if (header->bLength > size) {
+				err("ran out of descriptors parsing");
+				return -1;
+			}
+		
+			retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
+			if (retval < 0)
+				return retval;
+
+			buffer += retval;
+			parsed += retval;
+			size -= retval;
+		}
+
+		/* We check to see if it's an alternate to this one */
+		ifp = (struct usb_interface_descriptor *)buffer;
+		if (size < USB_DT_INTERFACE_SIZE ||
+		    ifp->bDescriptorType != USB_DT_INTERFACE ||
+		    !ifp->bAlternateSetting)
+			return parsed;
+	}
+
+	return parsed;
+}
+
+int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
+{
+	int i, retval, size;
+	struct usb_descriptor_header *header;
+
+	memcpy(config, buffer, USB_DT_CONFIG_SIZE);
+	le16_to_cpus(&config->wTotalLength);
+	size = config->wTotalLength;
+
+	if (config->bNumInterfaces > USB_MAXINTERFACES) {
+		warn("too many interfaces");
+		return -1;
+	}
+
+	config->interface = (struct usb_interface *)
+		kmalloc(config->bNumInterfaces *
+		sizeof(struct usb_interface), GFP_KERNEL);
+	dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces);
+	if (!config->interface) {
+		err("out of memory");
+		return -1;	
+	}
+
+	memset(config->interface, 0,
+	       config->bNumInterfaces * sizeof(struct usb_interface));
+
+	buffer += config->bLength;
+	size -= config->bLength;
+	
+	config->extra = NULL;
+	config->extralen = 0;
+
+	for (i = 0; i < config->bNumInterfaces; i++) {
+		int numskipped, len;
+		char *begin;
+
+		/* Skip over the rest of the Class Specific or Vendor */
+		/*  Specific descriptors */
+		begin = buffer;
+		numskipped = 0;
+		while (size >= sizeof(struct usb_descriptor_header)) {
+			header = (struct usb_descriptor_header *)buffer;
+
+			if ((header->bLength > size) || (header->bLength < 2)) {
+				err("invalid descriptor length of %d", header->bLength);
+				return -1;
+			}
+
+			/* 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) ||
+			    (header->bDescriptorType == USB_DT_DEVICE))
+				break;
+
+			dbg("skipping descriptor 0x%X", header->bDescriptorType);
+			numskipped++;
+
+			buffer += header->bLength;
+			size -= header->bLength;
+		}
+		if (numskipped)
+			dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
+
+		/* Copy any unknown descriptors into a storage area for */
+		/*  drivers to later parse */
+		len = (int)(buffer - begin);
+		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;
+			}
+		}
+
+		retval = usb_parse_interface(config->interface + i, buffer, size);
+		if (retval < 0)
+			return retval;
+
+		buffer += retval;
+		size -= retval;
+	}
+
+	return size;
+}
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally on disconnect/destroy path
+void usb_destroy_configuration(struct usb_device *dev)
+{
+	int c, i, j, k;
+	
+	if (!dev->config)
+		return;
+
+	if (dev->rawdescriptors) {
+		for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
+			kfree(dev->rawdescriptors[i]);
+
+		kfree(dev->rawdescriptors);
+	}
+
+	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
+		struct usb_config_descriptor *cf = &dev->config[c];
+
+		if (!cf->interface)
+			break;
+
+		for (i = 0; i < cf->bNumInterfaces; i++) {
+			struct usb_interface *ifp =
+				&cf->interface[i];
+				
+			if (!ifp->altsetting)
+				break;
+
+			for (j = 0; j < ifp->num_altsetting; j++) {
+				struct usb_interface_descriptor *as =
+					&ifp->altsetting[j];
+					
+				if(as->extra) {
+					kfree(as->extra);
+				}
+
+				if (!as->endpoint)
+					break;
+					
+				for(k = 0; k < as->bNumEndpoints; k++) {
+					if(as->endpoint[k].extra) {
+						kfree(as->endpoint[k].extra);
+					}
+				}	
+				kfree(as->endpoint);
+			}
+
+			kfree(ifp->altsetting);
+		}
+		kfree(cf->interface);
+	}
+	kfree(dev->config);
+}
+
+
+// hub-only!! ... and only in reset path, or usb_new_device()
+// (used by real hubs and virtual root hubs)
+int usb_get_configuration(struct usb_device *dev)
+{
+	int result;
+	unsigned int cfgno, length;
+	unsigned char *buffer;
+	unsigned char *bigbuffer;
+ 	struct usb_config_descriptor *desc;
+
+	if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
+		warn("too many configurations");
+		return -EINVAL;
+	}
+
+	if (dev->descriptor.bNumConfigurations < 1) {
+		warn("not enough configurations");
+		return -EINVAL;
+	}
+
+	dev->config = (struct usb_config_descriptor *)
+		kmalloc(dev->descriptor.bNumConfigurations *
+		sizeof(struct usb_config_descriptor), GFP_KERNEL);
+	if (!dev->config) {
+		err("out of memory");
+		return -ENOMEM;	
+	}
+	memset(dev->config, 0, dev->descriptor.bNumConfigurations *
+		sizeof(struct usb_config_descriptor));
+
+	dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
+		dev->descriptor.bNumConfigurations, GFP_KERNEL);
+	if (!dev->rawdescriptors) {
+		err("out of memory");
+		return -ENOMEM;
+	}
+
+	buffer = kmalloc(8, GFP_KERNEL);
+	if (!buffer) {
+		err("unable to allocate memory for configuration descriptors");
+		return -ENOMEM;
+	}
+	desc = (struct usb_config_descriptor *)buffer;
+
+	for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
+		/* We grab the first 8 bytes so we know how long the whole */
+		/*  configuration is */
+		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
+		if (result < 8) {
+			if (result < 0)
+				err("unable to get descriptor");
+			else {
+				err("config descriptor too short (expected %i, got %i)", 8, result);
+				result = -EINVAL;
+			}
+			goto err;
+		}
+
+  	  	/* Get the full buffer */
+		length = le16_to_cpu(desc->wTotalLength);
+
+		bigbuffer = kmalloc(length, GFP_KERNEL);
+		if (!bigbuffer) {
+			err("unable to allocate memory for configuration descriptors");
+			result = -ENOMEM;
+			goto err;
+		}
+
+		/* Now that we know the length, get the whole thing */
+		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
+		if (result < 0) {
+			err("couldn't get all of config descriptors");
+			kfree(bigbuffer);
+			goto err;
+		}	
+	
+		if (result < length) {
+			err("config descriptor too short (expected %i, got %i)", length, result);
+			result = -EINVAL;
+			kfree(bigbuffer);
+			goto err;
+		}
+
+		dev->rawdescriptors[cfgno] = bigbuffer;
+
+		result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
+		if (result > 0)
+			dbg("descriptor data left");
+		else if (result < 0) {
+			result = -EINVAL;
+			goto err;
+		}
+	}
+
+	kfree(buffer);
+	return 0;
+err:
+	kfree(buffer);
+	dev->descriptor.bNumConfigurations = cfgno;
+	return result;
+}
+
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Fri May 31 16:47:03 2002
+++ b/drivers/usb/core/usb.c	Fri May 31 16:47:03 2002
@@ -33,7 +33,6 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <asm/byteorder.h>
 
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
@@ -1035,390 +1034,6 @@
 
 /*-------------------------------------------------------------------*/
 
-static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
-{
-	struct usb_descriptor_header *header;
-	unsigned char *begin;
-	int parsed = 0, len, numskipped;
-
-	header = (struct usb_descriptor_header *)buffer;
-
-	/* Everything should be fine being passed into here, but we sanity */
-	/*  check JIC */
-	if (header->bLength > size) {
-		err("ran out of descriptors parsing");
-		return -1;
-	}
-		
-	if (header->bDescriptorType != USB_DT_ENDPOINT) {
-		warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
-			endpoint->bDescriptorType, USB_DT_ENDPOINT);
-		return parsed;
-	}
-
-	if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
-		memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
-	else
-		memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
-	
-	le16_to_cpus(&endpoint->wMaxPacketSize);
-
-	buffer += header->bLength;
-	size -= header->bLength;
-	parsed += header->bLength;
-
-	/* Skip over the rest of the Class Specific or Vendor Specific */
-	/*  descriptors */
-	begin = buffer;
-	numskipped = 0;
-	while (size >= sizeof(struct usb_descriptor_header)) {
-		header = (struct usb_descriptor_header *)buffer;
-
-		if (header->bLength < 2) {
-			err("invalid descriptor length of %d", header->bLength);
-			return -1;
-		}
-
-		/* 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) ||
-		    (header->bDescriptorType == USB_DT_DEVICE))
-			break;
-
-		dbg("skipping descriptor 0x%X",
-			header->bDescriptorType);
-		numskipped++;
-
-		buffer += header->bLength;
-		size -= header->bLength;
-		parsed += header->bLength;
-	}
-	if (numskipped)
-		dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
-
-	/* Copy any unknown descriptors into a storage area for drivers */
-	/*  to later parse */
-	len = (int)(buffer - begin);
-	if (!len) {
-		endpoint->extra = NULL;
-		endpoint->extralen = 0;
-		return parsed;
-	}
-
-	endpoint->extra = kmalloc(len, GFP_KERNEL);
-
-	if (!endpoint->extra) {
-		err("couldn't allocate memory for endpoint extra descriptors");
-		endpoint->extralen = 0;
-		return parsed;
-	}
-
-	memcpy(endpoint->extra, begin, len);
-	endpoint->extralen = len;
-
-	return parsed;
-}
-
-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;
-	struct usb_interface_descriptor *ifp;
-	unsigned char *begin;
-
-	interface->act_altsetting = 0;
-	interface->num_altsetting = 0;
-	interface->max_altsetting = USB_ALTSETTINGALLOC;
-
-	interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
-	
-	if (!interface->altsetting) {
-		err("couldn't kmalloc interface->altsetting");
-		return -1;
-	}
-
-	while (size > 0) {
-		if (interface->num_altsetting >= interface->max_altsetting) {
-			void *ptr;
-			int oldmas;
-
-			oldmas = interface->max_altsetting;
-			interface->max_altsetting += USB_ALTSETTINGALLOC;
-			if (interface->max_altsetting > USB_MAXALTSETTING) {
-				warn("too many alternate settings (max %d)",
-					USB_MAXALTSETTING);
-				return -1;
-			}
-
-			ptr = interface->altsetting;
-			interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
-			if (!interface->altsetting) {
-				err("couldn't kmalloc interface->altsetting");
-				interface->altsetting = ptr;
-				return -1;
-			}
-			memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas);
-
-			kfree(ptr);
-		}
-
-		ifp = interface->altsetting + interface->num_altsetting;
-		ifp->endpoint = NULL;
-		ifp->extra = NULL;
-		ifp->extralen = 0;
-		interface->num_altsetting++;
-
-		memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
-
-		/* Skip over the interface */
-		buffer += ifp->bLength;
-		parsed += ifp->bLength;
-		size -= ifp->bLength;
-
-		begin = buffer;
-		numskipped = 0;
-
-		/* Skip over any interface, class or vendor descriptors */
-		while (size >= sizeof(struct usb_descriptor_header)) {
-			header = (struct usb_descriptor_header *)buffer;
-
-			if (header->bLength < 2) {
-				err("invalid descriptor length of %d", header->bLength);
-				return -1;
-			}
-
-			/* 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) ||
-			    (header->bDescriptorType == USB_DT_DEVICE))
-				break;
-
-			numskipped++;
-
-			buffer += header->bLength;
-			parsed += header->bLength;
-			size -= header->bLength;
-		}
-
-		if (numskipped)
-			dbg("skipped %d class/vendor specific interface descriptors", numskipped);
-
-		/* Copy any unknown descriptors into a storage area for */
-		/*  drivers to later parse */
-		len = (int)(buffer - begin);
-		if (len) {
-			ifp->extra = kmalloc(len, GFP_KERNEL);
-
-			if (!ifp->extra) {
-				err("couldn't allocate memory for interface extra descriptors");
-				ifp->extralen = 0;
-				return -1;
-			}
-			memcpy(ifp->extra, begin, len);
-			ifp->extralen = len;
-		}
-
-		/* Did we hit an unexpected descriptor? */
-		header = (struct usb_descriptor_header *)buffer;
-		if ((size >= sizeof(struct usb_descriptor_header)) &&
-		    ((header->bDescriptorType == USB_DT_CONFIG) ||
-		     (header->bDescriptorType == USB_DT_DEVICE)))
-			return parsed;
-
-		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
-			warn("too many endpoints");
-			return -1;
-		}
-
-		ifp->endpoint = (struct usb_endpoint_descriptor *)
-			kmalloc(ifp->bNumEndpoints *
-			sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
-		if (!ifp->endpoint) {
-			err("out of memory");
-			return -1;	
-		}
-
-		memset(ifp->endpoint, 0, ifp->bNumEndpoints *
-			sizeof(struct usb_endpoint_descriptor));
-	
-		for (i = 0; i < ifp->bNumEndpoints; i++) {
-			header = (struct usb_descriptor_header *)buffer;
-
-			if (header->bLength > size) {
-				err("ran out of descriptors parsing");
-				return -1;
-			}
-		
-			retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
-			if (retval < 0)
-				return retval;
-
-			buffer += retval;
-			parsed += retval;
-			size -= retval;
-		}
-
-		/* We check to see if it's an alternate to this one */
-		ifp = (struct usb_interface_descriptor *)buffer;
-		if (size < USB_DT_INTERFACE_SIZE ||
-		    ifp->bDescriptorType != USB_DT_INTERFACE ||
-		    !ifp->bAlternateSetting)
-			return parsed;
-	}
-
-	return parsed;
-}
-
-int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
-{
-	int i, retval, size;
-	struct usb_descriptor_header *header;
-
-	memcpy(config, buffer, USB_DT_CONFIG_SIZE);
-	le16_to_cpus(&config->wTotalLength);
-	size = config->wTotalLength;
-
-	if (config->bNumInterfaces > USB_MAXINTERFACES) {
-		warn("too many interfaces");
-		return -1;
-	}
-
-	config->interface = (struct usb_interface *)
-		kmalloc(config->bNumInterfaces *
-		sizeof(struct usb_interface), GFP_KERNEL);
-	dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces);
-	if (!config->interface) {
-		err("out of memory");
-		return -1;	
-	}
-
-	memset(config->interface, 0,
-	       config->bNumInterfaces * sizeof(struct usb_interface));
-
-	buffer += config->bLength;
-	size -= config->bLength;
-	
-	config->extra = NULL;
-	config->extralen = 0;
-
-	for (i = 0; i < config->bNumInterfaces; i++) {
-		int numskipped, len;
-		char *begin;
-
-		/* Skip over the rest of the Class Specific or Vendor */
-		/*  Specific descriptors */
-		begin = buffer;
-		numskipped = 0;
-		while (size >= sizeof(struct usb_descriptor_header)) {
-			header = (struct usb_descriptor_header *)buffer;
-
-			if ((header->bLength > size) || (header->bLength < 2)) {
-				err("invalid descriptor length of %d", header->bLength);
-				return -1;
-			}
-
-			/* 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) ||
-			    (header->bDescriptorType == USB_DT_DEVICE))
-				break;
-
-			dbg("skipping descriptor 0x%X", header->bDescriptorType);
-			numskipped++;
-
-			buffer += header->bLength;
-			size -= header->bLength;
-		}
-		if (numskipped)
-			dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
-
-		/* Copy any unknown descriptors into a storage area for */
-		/*  drivers to later parse */
-		len = (int)(buffer - begin);
-		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;
-			}
-		}
-
-		retval = usb_parse_interface(config->interface + i, buffer, size);
-		if (retval < 0)
-			return retval;
-
-		buffer += retval;
-		size -= retval;
-	}
-
-	return size;
-}
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally on disconnect/destroy path
-void usb_destroy_configuration(struct usb_device *dev)
-{
-	int c, i, j, k;
-	
-	if (!dev->config)
-		return;
-
-	if (dev->rawdescriptors) {
-		for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
-			kfree(dev->rawdescriptors[i]);
-
-		kfree(dev->rawdescriptors);
-	}
-
-	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
-		struct usb_config_descriptor *cf = &dev->config[c];
-
-		if (!cf->interface)
-			break;
-
-		for (i = 0; i < cf->bNumInterfaces; i++) {
-			struct usb_interface *ifp =
-				&cf->interface[i];
-				
-			if (!ifp->altsetting)
-				break;
-
-			for (j = 0; j < ifp->num_altsetting; j++) {
-				struct usb_interface_descriptor *as =
-					&ifp->altsetting[j];
-					
-				if(as->extra) {
-					kfree(as->extra);
-				}
-
-				if (!as->endpoint)
-					break;
-					
-				for(k = 0; k < as->bNumEndpoints; k++) {
-					if(as->endpoint[k].extra) {
-						kfree(as->endpoint[k].extra);
-					}
-				}	
-				kfree(as->endpoint);
-			}
-
-			kfree(ifp->altsetting);
-		}
-		kfree(cf->interface);
-	}
-	kfree(dev->config);
-}
 
 /* for returning string descriptors in UTF-16LE */
 static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
@@ -1618,108 +1233,6 @@
 		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
 }
 
-
-// hub-only!! ... and only in reset path, or usb_new_device()
-// (used by real hubs and virtual root hubs)
-int usb_get_configuration(struct usb_device *dev)
-{
-	int result;
-	unsigned int cfgno, length;
-	unsigned char *buffer;
-	unsigned char *bigbuffer;
- 	struct usb_config_descriptor *desc;
-
-	if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
-		warn("too many configurations");
-		return -EINVAL;
-	}
-
-	if (dev->descriptor.bNumConfigurations < 1) {
-		warn("not enough configurations");
-		return -EINVAL;
-	}
-
-	dev->config = (struct usb_config_descriptor *)
-		kmalloc(dev->descriptor.bNumConfigurations *
-		sizeof(struct usb_config_descriptor), GFP_KERNEL);
-	if (!dev->config) {
-		err("out of memory");
-		return -ENOMEM;	
-	}
-	memset(dev->config, 0, dev->descriptor.bNumConfigurations *
-		sizeof(struct usb_config_descriptor));
-
-	dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
-		dev->descriptor.bNumConfigurations, GFP_KERNEL);
-	if (!dev->rawdescriptors) {
-		err("out of memory");
-		return -ENOMEM;
-	}
-
-	buffer = kmalloc(8, GFP_KERNEL);
-	if (!buffer) {
-		err("unable to allocate memory for configuration descriptors");
-		return -ENOMEM;
-	}
-	desc = (struct usb_config_descriptor *)buffer;
-
-	for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
-		/* We grab the first 8 bytes so we know how long the whole */
-		/*  configuration is */
-		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
-		if (result < 8) {
-			if (result < 0)
-				err("unable to get descriptor");
-			else {
-				err("config descriptor too short (expected %i, got %i)", 8, result);
-				result = -EINVAL;
-			}
-			goto err;
-		}
-
-  	  	/* Get the full buffer */
-		length = le16_to_cpu(desc->wTotalLength);
-
-		bigbuffer = kmalloc(length, GFP_KERNEL);
-		if (!bigbuffer) {
-			err("unable to allocate memory for configuration descriptors");
-			result = -ENOMEM;
-			goto err;
-		}
-
-		/* Now that we know the length, get the whole thing */
-		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
-		if (result < 0) {
-			err("couldn't get all of config descriptors");
-			kfree(bigbuffer);
-			goto err;
-		}	
-	
-		if (result < length) {
-			err("config descriptor too short (expected %i, got %i)", length, result);
-			result = -EINVAL;
-			kfree(bigbuffer);
-			goto err;
-		}
-
-		dev->rawdescriptors[cfgno] = bigbuffer;
-
-		result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
-		if (result > 0)
-			dbg("descriptor data left");
-		else if (result < 0) {
-			result = -EINVAL;
-			goto err;
-		}
-	}
-
-	kfree(buffer);
-	return 0;
-err:
-	kfree(buffer);
-	dev->descriptor.bNumConfigurations = cfgno;
-	return result;
-}
 
 /*
  * By the time we get here, the device has gotten a new device ID
