ChangeSet 1.1673.8.8, 2004/03/25 15:16:15-08:00, [EMAIL PROTECTED]
[PATCH] USB: Improve core/config.c error messages
This patch improves error reporting in the configuration parsing routines.
It also adds a few extra minor tweaks.
#include linux/config.h and make the usual DEBUG settings
available.
Use the driver-model dev_xxx() macros for log output.
Be much more explicit about the nature of errors, including
configuration, interface, and altsetting numbers where
appropriate.
Log fatal problems as errors, non-fatal ones as warnings.
Remove a #define'd constant that is already set in linux/usb.h.
Fix some variables declared as pointer to char that really
should be pointers to unsigned char.
Replace a whole bunch of "out-of-memory" error messages with
a single message.
Wrap source lines that are longer than 80 columns (but not
log output lines!).
Clean up the logic for detecting errors when retrieving a
configuration descriptor.
Apart from the log messages themselves, this introduces no functional
changes.
drivers/usb/core/config.c | 225 ++++++++++++++++++++++++++--------------------
1 files changed, 132 insertions(+), 93 deletions(-)
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c Wed Apr 14 14:39:47 2004
+++ b/drivers/usb/core/config.c Wed Apr 14 14:39:47 2004
@@ -1,18 +1,25 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#endif
+
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/device.h>
#include <asm/byteorder.h>
#define USB_MAXALTSETTING 128 /* Hard limit */
#define USB_MAXENDPOINTS 30 /* Hard limit */
-/* these maximums are arbitrary */
-#define USB_MAXCONFIG 8
-#define USB_MAXINTERFACES 32
+#define USB_MAXCONFIG 8 /* Arbitrary limit */
-static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char
*buffer, int size)
+static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ int asnum, struct usb_host_endpoint *endpoint,
+ unsigned char *buffer, int size)
{
unsigned char *buffer0 = buffer;
struct usb_descriptor_header *header;
@@ -21,8 +28,11 @@
header = (struct usb_descriptor_header *)buffer;
if (header->bDescriptorType != USB_DT_ENDPOINT) {
- warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X",
- header->bDescriptorType, USB_DT_ENDPOINT);
+ dev_err(ddev, "config %d interface %d altsetting %d has an "
+ "unexpected descriptor of type 0x%X, "
+ "expecting endpoint type 0x%X\n",
+ cfgno, inum, asnum,
+ header->bDescriptorType, USB_DT_ENDPOINT);
return -EINVAL;
}
@@ -31,13 +41,16 @@
else if (header->bLength >= USB_DT_ENDPOINT_SIZE)
memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE);
else {
- warn("invalid endpoint descriptor");
+ dev_err(ddev, "config %d interface %d altsetting %d has an "
+ "invalid endpoint descriptor of length %d\n",
+ cfgno, inum, asnum, header->bLength);
return -EINVAL;
}
if ((endpoint->desc.bEndpointAddress & ~USB_ENDPOINT_DIR_MASK) >= 16) {
- warn("invalid endpoint address 0x%X",
- endpoint->desc.bEndpointAddress);
+ dev_err(ddev, "config %d interface %d altsetting %d has an "
+ "invalid endpoint with address 0x%X\n",
+ cfgno, inum, asnum, endpoint->desc.bEndpointAddress);
return -EINVAL;
}
@@ -57,14 +70,16 @@
(header->bDescriptorType == USB_DT_INTERFACE))
break;
- dbg("skipping descriptor 0x%X", header->bDescriptorType);
+ dev_dbg(ddev, "skipping descriptor 0x%X\n",
+ header->bDescriptorType);
numskipped++;
buffer += header->bLength;
size -= header->bLength;
}
if (numskipped) {
- dbg("skipped %d class/vendor specific endpoint descriptors",
numskipped);
+ dev_dbg(ddev, "skipped %d class/vendor specific endpoint "
+ "descriptors\n", numskipped);
endpoint->extra = begin;
endpoint->extralen = buffer - begin;
}
@@ -87,7 +102,8 @@
kfree(intf);
}
-static int usb_parse_interface(struct usb_host_config *config, unsigned char *buffer,
int size)
+static int usb_parse_interface(struct device *ddev, int cfgno,
+ struct usb_host_config *config, unsigned char *buffer, int size)
{
unsigned char *buffer0 = buffer;
struct usb_interface_descriptor *d;
@@ -101,8 +117,9 @@
d = (struct usb_interface_descriptor *) buffer;
if (d->bDescriptorType != USB_DT_INTERFACE) {
- warn("unexpected descriptor 0x%X, expecting interface, 0x%X",
- d->bDescriptorType, USB_DT_INTERFACE);
+ dev_err(ddev, "config %d has an unexpected descriptor of type "
+ "0x%X, expecting interface type 0x%X\n",
+ cfgno, d->bDescriptorType, USB_DT_INTERFACE);
return -EINVAL;
}
@@ -126,15 +143,16 @@
interface = config->interface[inum];
asnum = d->bAlternateSetting;
if (asnum >= interface->num_altsetting) {
- warn("invalid alternate setting %d for interface %d",
- asnum, inum);
+ dev_err(ddev, "config %d interface %d has an invalid "
+ "alternate setting number: %d but max is %d\n",
+ cfgno, inum, asnum, interface->num_altsetting - 1);
return -EINVAL;
}
ifp = &interface->altsetting[asnum];
if (ifp->desc.bLength) {
- warn("duplicate descriptor for interface %d altsetting %d",
- inum, asnum);
+ dev_err(ddev, "Duplicate descriptor for config %d "
+ "interface %d altsetting %d\n", cfgno, inum, asnum);
return -EINVAL;
}
memcpy(&ifp->desc, buffer, USB_DT_INTERFACE_SIZE);
@@ -153,39 +171,44 @@
(header->bDescriptorType == USB_DT_ENDPOINT))
break;
- dbg("skipping descriptor 0x%X", header->bDescriptorType);
+ dev_dbg(ddev, "skipping descriptor 0x%X\n",
+ header->bDescriptorType);
numskipped++;
buffer += header->bLength;
size -= header->bLength;
}
if (numskipped) {
- dbg("skipped %d class/vendor specific interface descriptors",
numskipped);
+ dev_dbg(ddev, "skipped %d class/vendor specific "
+ "interface descriptors\n", numskipped);
ifp->extra = begin;
ifp->extralen = buffer - begin;
}
if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
- warn("too many endpoints for interface %d altsetting %d",
- inum, asnum);
+ dev_err(ddev, "too many endpoints for config %d interface %d "
+ "altsetting %d: %d, maximum allowed: %d\n",
+ cfgno, inum, asnum, ifp->desc.bNumEndpoints,
+ USB_MAXENDPOINTS);
return -EINVAL;
}
len = ifp->desc.bNumEndpoints * sizeof(struct usb_host_endpoint);
ifp->endpoint = kmalloc(len, GFP_KERNEL);
- if (!ifp->endpoint) {
- err("out of memory");
+ if (!ifp->endpoint)
return -ENOMEM;
- }
memset(ifp->endpoint, 0, len);
for (i = 0; i < ifp->desc.bNumEndpoints; i++) {
if (size < USB_DT_ENDPOINT_SIZE) {
- warn("ran out of descriptors while parsing endpoints");
+ dev_err(ddev, "too few endpoint descriptors for "
+ "config %d interface %d altsetting %d\n",
+ cfgno, inum, asnum);
return -EINVAL;
}
- retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
+ retval = usb_parse_endpoint(ddev, cfgno, inum, asnum,
+ ifp->endpoint + i, buffer, size);
if (retval < 0)
return retval;
@@ -196,41 +219,45 @@
return buffer - buffer0;
}
-int usb_parse_configuration(struct usb_host_config *config, char *buffer, int size)
+int usb_parse_configuration(struct device *ddev, int cfgidx,
+ struct usb_host_config *config, unsigned char *buffer, int size)
{
+ int cfgno;
int nintf, nintf_orig;
int i, j;
struct usb_interface *interface;
- char *buffer2;
+ unsigned char *buffer2;
int size2;
struct usb_descriptor_header *header;
int numskipped, len;
- char *begin;
+ unsigned char *begin;
int retval;
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
if (config->desc.bDescriptorType != USB_DT_CONFIG ||
config->desc.bLength < USB_DT_CONFIG_SIZE) {
- warn("invalid configuration descriptor");
+ dev_err(ddev, "invalid descriptor for config index %d: "
+ "type = 0x%X, length = %d\n", cfgidx,
+ config->desc.bDescriptorType, config->desc.bLength);
return -EINVAL;
}
config->desc.wTotalLength = size;
+ cfgno = config->desc.bConfigurationValue;
nintf = nintf_orig = config->desc.bNumInterfaces;
if (nintf > USB_MAXINTERFACES) {
- warn("too many interfaces (%d max %d)",
- nintf, USB_MAXINTERFACES);
+ dev_warn(ddev, "config %d has too many interfaces: %d, "
+ "using maximum allowed: %d\n",
+ cfgno, nintf, USB_MAXINTERFACES);
config->desc.bNumInterfaces = nintf = USB_MAXINTERFACES;
}
for (i = 0; i < nintf; ++i) {
interface = config->interface[i] =
kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
- dbg("kmalloc IF %p, numif %i", interface, i);
- if (!interface) {
- err("out of memory");
+ dev_dbg(ddev, "kmalloc IF %p, numif %i\n", interface, i);
+ if (!interface)
return -ENOMEM;
- }
memset(interface, 0, sizeof(struct usb_interface));
}
@@ -242,7 +269,8 @@
while (size2 >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *) buffer2;
if ((header->bLength > size2) || (header->bLength < 2)) {
- warn("invalid descriptor of length %d", header->bLength);
+ dev_err(ddev, "config %d has an invalid descriptor "
+ "of length %d\n", cfgno, header->bLength);
return -EINVAL;
}
@@ -250,14 +278,17 @@
struct usb_interface_descriptor *d;
if (header->bLength < USB_DT_INTERFACE_SIZE) {
- warn("invalid interface descriptor");
+ dev_err(ddev, "config %d has an invalid "
+ "interface descriptor of length %d\n",
+ cfgno, header->bLength);
return -EINVAL;
}
d = (struct usb_interface_descriptor *) header;
i = d->bInterfaceNumber;
if (i >= nintf_orig) {
- warn("invalid interface number (%d/%d)",
- i, nintf_orig);
+ dev_err(ddev, "config %d has an invalid "
+ "interface number: %d but max is %d\n",
+ cfgno, i, nintf_orig - 1);
return -EINVAL;
}
if (i < nintf)
@@ -265,7 +296,9 @@
} else if ((header->bDescriptorType == USB_DT_DEVICE ||
header->bDescriptorType == USB_DT_CONFIG) && j) {
- warn("unexpected descriptor type 0x%X",
header->bDescriptorType);
+ dev_err(ddev, "config %d contains an unexpected "
+ "descriptor of type 0x%X\n",
+ cfgno, header->bDescriptorType);
return -EINVAL;
}
@@ -278,21 +311,24 @@
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
interface = config->interface[i];
if (interface->num_altsetting > USB_MAXALTSETTING) {
- warn("too many alternate settings for interface %d (%d max
%d)\n",
- i, interface->num_altsetting, USB_MAXALTSETTING);
+ dev_err(ddev, "too many alternate settings for "
+ "config %d interface %d: %d, "
+ "maximum allowed: %d\n",
+ cfgno, i, interface->num_altsetting,
+ USB_MAXALTSETTING);
return -EINVAL;
}
if (interface->num_altsetting == 0) {
- warn("no alternate settings for interface %d", i);
+ dev_err(ddev, "config %d has no interface number "
+ "%d\n", cfgno, i);
return -EINVAL;
}
- len = sizeof(*interface->altsetting) * interface->num_altsetting;
+ len = sizeof(*interface->altsetting) *
+ interface->num_altsetting;
interface->altsetting = kmalloc(len, GFP_KERNEL);
- if (!interface->altsetting) {
- err("couldn't kmalloc interface->altsetting");
+ if (!interface->altsetting)
return -ENOMEM;
- }
memset(interface->altsetting, 0, len);
}
@@ -310,21 +346,24 @@
(header->bDescriptorType == USB_DT_INTERFACE))
break;
- dbg("skipping descriptor 0x%X", header->bDescriptorType);
+ dev_dbg(ddev, "skipping descriptor 0x%X\n",
+ header->bDescriptorType);
numskipped++;
buffer += header->bLength;
size -= header->bLength;
}
if (numskipped) {
- dbg("skipped %d class/vendor specific configuration descriptors",
numskipped);
+ dev_dbg(ddev, "skipped %d class/vendor specific configuration "
+ "descriptors\n", numskipped);
config->extra = begin;
config->extralen = buffer - begin;
}
/* Parse all the interface/altsetting descriptors */
while (size >= sizeof(struct usb_descriptor_header)) {
- retval = usb_parse_interface(config, buffer, size);
+ retval = usb_parse_interface(ddev, cfgno, config,
+ buffer, size);
if (retval < 0)
return retval;
@@ -337,7 +376,8 @@
interface = config->interface[i];
for (j = 0; j < interface->num_altsetting; ++j) {
if (!interface->altsetting[j].desc.bLength) {
- warn("missing altsetting %d for interface %d", j, i);
+ dev_err(ddev, "config %d interface %d has no "
+ "altsetting %d\n", cfgno, i, j);
return -EINVAL;
}
}
@@ -380,81 +420,77 @@
// (used by real hubs and virtual root hubs)
int usb_get_configuration(struct usb_device *dev)
{
+ struct device *ddev = &dev->dev;
int ncfg = dev->descriptor.bNumConfigurations;
- int result;
+ int result = -ENOMEM;
unsigned int cfgno, length;
unsigned char *buffer;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
if (ncfg > USB_MAXCONFIG) {
- warn("too many configurations (%d max %d)",
- ncfg, USB_MAXCONFIG);
+ dev_warn(ddev, "too many configurations: %d, "
+ "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
}
if (ncfg < 1) {
- warn("no configurations");
+ dev_err(ddev, "no configurations\n");
return -EINVAL;
}
length = ncfg * sizeof(struct usb_host_config);
dev->config = kmalloc(length, GFP_KERNEL);
- if (!dev->config) {
- err("out of memory");
- return -ENOMEM;
- }
+ if (!dev->config)
+ goto err2;
memset(dev->config, 0, length);
length = ncfg * sizeof(char *);
dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
- if (!dev->rawdescriptors) {
- err("out of memory");
- return -ENOMEM;
- }
+ if (!dev->rawdescriptors)
+ goto err2;
memset(dev->rawdescriptors, 0, length);
buffer = kmalloc(8, GFP_KERNEL);
- if (!buffer) {
- err("unable to allocate memory for configuration descriptors");
- return -ENOMEM;
- }
+ if (!buffer)
+ goto err2;
desc = (struct usb_config_descriptor *)buffer;
for (cfgno = 0; cfgno < ncfg; 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 {
- warn("config descriptor too short (expected %i, got
%i)", 8, result);
- result = -EINVAL;
- }
+ /* configuration is */
+ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
+ buffer, 8);
+ if (result < 0) {
+ dev_err(ddev, "unable to read config index %d "
+ "descriptor\n", cfgno);
+ goto err;
+ } else if (result < 8) {
+ dev_err(ddev, "config index %d descriptor too short "
+ "(expected %i, got %i)\n", cfgno, 8, result);
+ result = -EINVAL;
goto err;
}
+ length = max((int) le16_to_cpu(desc->wTotalLength),
+ USB_DT_CONFIG_SIZE);
- /* Get the full buffer */
- length = max((int) le16_to_cpu(desc->wTotalLength),
USB_DT_CONFIG_SIZE);
-
+ /* Now that we know the length, get the whole thing */
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);
+ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
+ bigbuffer, length);
if (result < 0) {
- err("couldn't get all of config descriptors");
+ dev_err(ddev, "unable to read config index %d "
+ "descriptor\n", cfgno);
kfree(bigbuffer);
goto err;
}
-
if (result < length) {
- err("config descriptor too short (expected %i, got %i)",
length, result);
+ dev_err(ddev, "config index %d descriptor too short "
+ "(expected %i, got %i)\n", cfgno, length, result);
result = -EINVAL;
kfree(bigbuffer);
goto err;
@@ -462,20 +498,23 @@
dev->rawdescriptors[cfgno] = bigbuffer;
- result = usb_parse_configuration(&dev->config[cfgno], bigbuffer,
length);
+ result = usb_parse_configuration(&dev->dev, cfgno,
+ &dev->config[cfgno], bigbuffer, length);
if (result > 0)
- dbg("descriptor data left");
+ dev_dbg(ddev, "config index %d descriptor has %d "
+ "excess byte(s)\n", cfgno, result);
else if (result < 0) {
++cfgno;
goto err;
}
}
+ result = 0;
- kfree(buffer);
- return 0;
err:
kfree(buffer);
dev->descriptor.bNumConfigurations = cfgno;
+err2:
+ if (result == -ENOMEM)
+ dev_err(ddev, "out of memory\n");
return result;
}
-
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel