patch_name:	usb_fakeconfig2420.patch
patch_version:	2003-07-21.09:58:42
author:		Randy.Dunlap <rddunlap AT osdl.org>
description:	_
product:	Linux
product_versions: linux-2420
changelog:	_
URL:		_
requires:	_
conflicts:	_
maintainer:	_
diffstat:	TBD

diff -Naur ./drivers/usb/usb.c~fake ./drivers/usb/usb.c
--- ./drivers/usb/usb.c~fake	2002-11-28 15:53:15.000000000 -0800
+++ ./drivers/usb/usb.c	2003-07-21 09:57:58.000000000 -0700
@@ -2029,6 +2029,53 @@
 		(type << 8) + id, ifnum, buf, size, HZ);
 }
 
+#define CONFIG_USB_FAKE_CONFIGS	1
+#ifdef CONFIG_USB_FAKE_CONFIGS
+/*
+ * build_config:
+ * for an invalid USB device that reports 0 configurations, this builds
+ * a config descriptor, interface descriptor, and endpoint descriptor.
+ */
+static int build_config(struct usb_device *dev, unsigned char index, void *buf, int size)
+{
+	struct usb_config_descriptor *config = (struct usb_config_descriptor *)buf;
+	struct usb_interface_descriptor *intf = (void *)config
+		+ USB_DT_CONFIG_SIZE;
+	struct usb_endpoint_descriptor *endp = (void *)intf
+		+ USB_DT_INTERFACE_SIZE;
+
+	memset(buf, 0, size);
+
+	config->bLength = USB_DT_CONFIG_SIZE;
+	config->bDescriptorType = USB_DT_CONFIG;
+	config->wTotalLength = cpu_to_le16(
+		USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE + USB_DT_ENDPOINT_SIZE);
+	config->bNumInterfaces = 1;
+	config->bConfigurationValue = 1;
+	config->MaxPower = 50;		/* => 100 mA */
+
+	intf->bLength = USB_DT_INTERFACE_SIZE;
+	intf->bDescriptorType = USB_DT_INTERFACE;
+	intf->bInterfaceNumber = 1;
+	intf->bAlternateSetting = 1;
+	intf->bNumEndpoints = 1;	/* try with output endpoint only */
+	intf->bInterfaceClass = USB_CLASS_PRINTER;
+
+	endp->bLength = USB_DT_ENDPOINT_SIZE;
+	endp->bDescriptorType = USB_DT_ENDPOINT;
+	endp->bEndpointAddress = USB_DIR_OUT | 1;
+	endp->bmAttributes = USB_ENDPOINT_XFER_BULK;
+	endp->wMaxPacketSize = cpu_to_le16(64);
+
+	return size;
+}
+#else
+static int build_config(struct usb_device *dev, unsigned char index, void *buf, int size)
+{
+	return -EINVAL;
+}
+#endif
+
 int usb_get_configuration(struct usb_device *dev)
 {
 	int result;
@@ -2036,6 +2083,7 @@
 	unsigned char *buffer;
 	unsigned char *bigbuffer;
  	struct usb_config_descriptor *desc;
+	int fake_config = 0;
 
 	if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
 		warn("too many configurations");
@@ -2044,7 +2092,12 @@
 
 	if (dev->descriptor.bNumConfigurations < 1) {
 		warn("not enough configurations");
+#ifdef CONFIG_USB_FAKE_CONFIGS
+		fake_config = dev->descriptor.bNumConfigurations = 1;
+		warn("faking a USB config for this device");
+#else
 		return -EINVAL;
+#endif
 	}
 
 	dev->config = (struct usb_config_descriptor *)
@@ -2074,19 +2127,25 @@
 	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;
+		if (!fake_config) {
+			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;
 			}
-			goto err;
-		}
 
-  	  	/* Get the full buffer */
-		length = le16_to_cpu(desc->wTotalLength);
+  	  		/* Get the full buffer */
+			length = le16_to_cpu(desc->wTotalLength);
+		}
+		else {
+			result = length =
+				USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE + USB_DT_ENDPOINT_SIZE;
+		}
 
 		bigbuffer = kmalloc(length, GFP_KERNEL);
 		if (!bigbuffer) {
@@ -2096,7 +2155,10 @@
 		}
 
 		/* Now that we know the length, get the whole thing */
-		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
+		if (fake_config)
+			result = build_config(dev, cfgno, bigbuffer, length);
+		else
+			result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
 		if (result < 0) {
 			err("couldn't get all of config descriptors");
 			kfree(bigbuffer);
