ChangeSet 1.1673.8.9, 2004/03/25 15:17:16-08:00, [EMAIL PROTECTED]
[PATCH] USB: Code improvements for core/config.c
This patch makes some improvements to the code in config.c.
Create a subroutine to handle the repeated task of skipping
forward to the next descriptor of a certain type.
Remove some fairly useless debugging messages (they could
never even have been enabled in the pre-as221 code).
Verify that endpoint descriptors don't have an address
equal to 0 (as well as not being above 15).
Rename some local variables so they are a little more
consistent and meaningful.
Despite all the changes, the functionality should remain the same.
Please apply.
drivers/usb/core/config.c | 235 +++++++++++++++++++---------------------------
1 files changed, 101 insertions(+), 134 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:42 2004
+++ b/drivers/usb/core/config.c Wed Apr 14 14:39:42 2004
@@ -17,14 +17,38 @@
#define USB_MAXCONFIG 8 /* Arbitrary limit */
+
+static int find_next_descriptor(unsigned char *buffer, int size,
+ int dt1, int dt2, int *num_skipped)
+{
+ struct usb_descriptor_header *h;
+ int n = 0;
+ unsigned char *buffer0 = buffer;
+
+ /* Find the next descriptor of type dt1 or dt2 */
+ while (size >= sizeof(struct usb_descriptor_header)) {
+ h = (struct usb_descriptor_header *) buffer;
+ if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2)
+ break;
+ buffer += h->bLength;
+ size -= h->bLength;
+ ++n;
+ }
+
+ /* Store the number of descriptors skipped and return the
+ * number of bytes skipped */
+ if (num_skipped)
+ *num_skipped = n;
+ return buffer - buffer0;
+}
+
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;
- unsigned char *begin;
- int numskipped;
+ int n, i;
header = (struct usb_descriptor_header *)buffer;
if (header->bDescriptorType != USB_DT_ENDPOINT) {
@@ -47,7 +71,8 @@
return -EINVAL;
}
- if ((endpoint->desc.bEndpointAddress & ~USB_ENDPOINT_DIR_MASK) >= 16) {
+ i = endpoint->desc.bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
+ if (i >= 16 || i == 0) {
dev_err(ddev, "config %d interface %d altsetting %d has an "
"invalid endpoint with address 0x%X\n",
cfgno, inum, asnum, endpoint->desc.bEndpointAddress);
@@ -59,32 +84,16 @@
buffer += header->bLength;
size -= header->bLength;
- /* Skip over any Class Specific or Vendor Specific descriptors */
- begin = buffer;
- numskipped = 0;
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *)buffer;
-
- /* If we find another "proper" descriptor then we're done */
- if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
- (header->bDescriptorType == USB_DT_INTERFACE))
- break;
-
- dev_dbg(ddev, "skipping descriptor 0x%X\n",
- header->bDescriptorType);
- numskipped++;
-
- buffer += header->bLength;
- size -= header->bLength;
- }
- if (numskipped) {
+ /* Skip over any Class Specific or Vendor Specific descriptors;
+ * find the next endpoint or interface descriptor */
+ endpoint->extra = buffer;
+ i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
+ USB_DT_INTERFACE, &n);
+ endpoint->extralen = i;
+ if (n > 0)
dev_dbg(ddev, "skipped %d class/vendor specific endpoint "
- "descriptors\n", numskipped);
- endpoint->extra = begin;
- endpoint->extralen = buffer - begin;
- }
-
- return buffer - buffer0;
+ "descriptors\n", n);
+ return buffer - buffer0 + i;
}
static void usb_free_intf(struct usb_interface *intf)
@@ -93,9 +102,9 @@
if (intf->altsetting) {
for (j = 0; j < intf->num_altsetting; j++) {
- struct usb_host_interface *as = &intf->altsetting[j];
+ struct usb_host_interface *alt = &intf->altsetting[j];
- kfree(as->endpoint);
+ kfree(alt->endpoint);
}
kfree(intf->altsetting);
}
@@ -109,13 +118,14 @@
struct usb_interface_descriptor *d;
int inum, asnum;
struct usb_interface *interface;
- struct usb_host_interface *ifp;
- int len, numskipped;
- struct usb_descriptor_header *header;
- unsigned char *begin;
- int i, retval;
+ struct usb_host_interface *alt;
+ int i, n;
+ int len, retval;
d = (struct usb_interface_descriptor *) buffer;
+ buffer += d->bLength;
+ size -= d->bLength;
+
if (d->bDescriptorType != USB_DT_INTERFACE) {
dev_err(ddev, "config %d has an unexpected descriptor of type "
"0x%X, expecting interface type 0x%X\n",
@@ -124,21 +134,8 @@
}
inum = d->bInterfaceNumber;
- if (inum >= config->desc.bNumInterfaces) {
-
- /* Skip to the next interface descriptor */
- buffer += d->bLength;
- size -= d->bLength;
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *) buffer;
-
- if (header->bDescriptorType == USB_DT_INTERFACE)
- break;
- buffer += header->bLength;
- size -= header->bLength;
- }
- return buffer - buffer0;
- }
+ if (inum >= config->desc.bNumInterfaces)
+ goto skip_to_next_interface_descriptor;
interface = config->interface[inum];
asnum = d->bAlternateSetting;
@@ -149,57 +146,41 @@
return -EINVAL;
}
- ifp = &interface->altsetting[asnum];
- if (ifp->desc.bLength) {
+ alt = &interface->altsetting[asnum];
+ if (alt->desc.bLength) {
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);
+ memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);
- buffer += d->bLength;
- size -= d->bLength;
-
- /* Skip over any Class Specific or Vendor Specific descriptors */
- begin = buffer;
- numskipped = 0;
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *)buffer;
-
- /* If we find another "proper" descriptor then we're done */
- if ((header->bDescriptorType == USB_DT_INTERFACE) ||
- (header->bDescriptorType == USB_DT_ENDPOINT))
- break;
-
- dev_dbg(ddev, "skipping descriptor 0x%X\n",
- header->bDescriptorType);
- numskipped++;
-
- buffer += header->bLength;
- size -= header->bLength;
- }
- if (numskipped) {
+ /* Skip over any Class Specific or Vendor Specific descriptors;
+ * find the first endpoint or interface descriptor */
+ alt->extra = buffer;
+ i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
+ USB_DT_INTERFACE, &n);
+ alt->extralen = i;
+ if (n > 0)
dev_dbg(ddev, "skipped %d class/vendor specific "
- "interface descriptors\n", numskipped);
- ifp->extra = begin;
- ifp->extralen = buffer - begin;
- }
+ "interface descriptors\n", n);
+ buffer += i;
+ size -= i;
- if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
+ if (alt->desc.bNumEndpoints > USB_MAXENDPOINTS) {
dev_err(ddev, "too many endpoints for config %d interface %d "
"altsetting %d: %d, maximum allowed: %d\n",
- cfgno, inum, asnum, ifp->desc.bNumEndpoints,
+ cfgno, inum, asnum, alt->desc.bNumEndpoints,
USB_MAXENDPOINTS);
return -EINVAL;
}
- len = ifp->desc.bNumEndpoints * sizeof(struct usb_host_endpoint);
- ifp->endpoint = kmalloc(len, GFP_KERNEL);
- if (!ifp->endpoint)
+ len = alt->desc.bNumEndpoints * sizeof(struct usb_host_endpoint);
+ alt->endpoint = kmalloc(len, GFP_KERNEL);
+ if (!alt->endpoint)
return -ENOMEM;
- memset(ifp->endpoint, 0, len);
+ memset(alt->endpoint, 0, len);
- for (i = 0; i < ifp->desc.bNumEndpoints; i++) {
+ for (i = 0; i < alt->desc.bNumEndpoints; i++) {
if (size < USB_DT_ENDPOINT_SIZE) {
dev_err(ddev, "too few endpoint descriptors for "
"config %d interface %d altsetting %d\n",
@@ -208,15 +189,19 @@
}
retval = usb_parse_endpoint(ddev, cfgno, inum, asnum,
- ifp->endpoint + i, buffer, size);
+ alt->endpoint + i, buffer, size);
if (retval < 0)
return retval;
buffer += retval;
size -= retval;
}
-
return buffer - buffer0;
+
+skip_to_next_interface_descriptor:
+ i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
+ USB_DT_INTERFACE, NULL);
+ return buffer - buffer0 + i;
}
int usb_parse_configuration(struct device *ddev, int cfgidx,
@@ -224,14 +209,12 @@
{
int cfgno;
int nintf, nintf_orig;
- int i, j;
+ int i, j, n;
struct usb_interface *interface;
unsigned char *buffer2;
int size2;
struct usb_descriptor_header *header;
- int numskipped, len;
- unsigned char *begin;
- int retval;
+ int len, retval;
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
if (config->desc.bDescriptorType != USB_DT_CONFIG ||
@@ -244,6 +227,9 @@
config->desc.wTotalLength = size;
cfgno = config->desc.bConfigurationValue;
+ buffer += config->desc.bLength;
+ size -= config->desc.bLength;
+
nintf = nintf_orig = config->desc.bNumInterfaces;
if (nintf > USB_MAXINTERFACES) {
dev_warn(ddev, "config %d has too many interfaces: %d, "
@@ -255,7 +241,6 @@
for (i = 0; i < nintf; ++i) {
interface = config->interface[i] =
kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
- dev_dbg(ddev, "kmalloc IF %p, numif %i\n", interface, i);
if (!interface)
return -ENOMEM;
memset(interface, 0, sizeof(struct usb_interface));
@@ -263,10 +248,10 @@
/* Go through the descriptors, checking their length and counting the
* number of altsettings for each interface */
- buffer2 = buffer;
- size2 = size;
- j = 0;
- while (size2 >= sizeof(struct usb_descriptor_header)) {
+ for ((buffer2 = buffer, size2 = size);
+ size2 >= sizeof(struct usb_descriptor_header);
+ (buffer2 += header->bLength, size2 -= header->bLength)) {
+
header = (struct usb_descriptor_header *) buffer2;
if ((header->bLength > size2) || (header->bLength < 2)) {
dev_err(ddev, "config %d has an invalid descriptor "
@@ -277,13 +262,14 @@
if (header->bDescriptorType == USB_DT_INTERFACE) {
struct usb_interface_descriptor *d;
- if (header->bLength < USB_DT_INTERFACE_SIZE) {
+ d = (struct usb_interface_descriptor *) header;
+ if (d->bLength < USB_DT_INTERFACE_SIZE) {
dev_err(ddev, "config %d has an invalid "
"interface descriptor of length %d\n",
- cfgno, header->bLength);
+ cfgno, d->bLength);
return -EINVAL;
}
- d = (struct usb_interface_descriptor *) header;
+
i = d->bInterfaceNumber;
if (i >= nintf_orig) {
dev_err(ddev, "config %d has an invalid "
@@ -294,21 +280,18 @@
if (i < nintf)
++config->interface[i]->num_altsetting;
- } else if ((header->bDescriptorType == USB_DT_DEVICE ||
- header->bDescriptorType == USB_DT_CONFIG) && j) {
+ } else if (header->bDescriptorType == USB_DT_DEVICE ||
+ header->bDescriptorType == USB_DT_CONFIG) {
dev_err(ddev, "config %d contains an unexpected "
"descriptor of type 0x%X\n",
cfgno, header->bDescriptorType);
return -EINVAL;
}
- j = 1;
- buffer2 += header->bLength;
- size2 -= header->bLength;
- }
+ } /* for ((buffer2 = buffer, size2 = size); ...) */
/* Allocate the altsetting arrays */
- for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ for (i = 0; i < nintf; ++i) {
interface = config->interface[i];
if (interface->num_altsetting > USB_MAXALTSETTING) {
dev_err(ddev, "too many alternate settings for "
@@ -332,33 +315,17 @@
memset(interface->altsetting, 0, len);
}
- buffer += config->desc.bLength;
- size -= config->desc.bLength;
-
- /* Skip over any Class Specific or Vendor Specific descriptors */
- begin = buffer;
- numskipped = 0;
- while (size >= sizeof(struct usb_descriptor_header)) {
- header = (struct usb_descriptor_header *)buffer;
-
- /* If we find another "proper" descriptor then we're done */
- if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
- (header->bDescriptorType == USB_DT_INTERFACE))
- break;
-
- dev_dbg(ddev, "skipping descriptor 0x%X\n",
- header->bDescriptorType);
- numskipped++;
-
- buffer += header->bLength;
- size -= header->bLength;
- }
- if (numskipped) {
- dev_dbg(ddev, "skipped %d class/vendor specific configuration "
- "descriptors\n", numskipped);
- config->extra = begin;
- config->extralen = buffer - begin;
- }
+ /* Skip over any Class Specific or Vendor Specific descriptors;
+ * find the first interface descriptor */
+ config->extra = buffer;
+ i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
+ USB_DT_INTERFACE, &n);
+ config->extralen = i;
+ if (n > 0)
+ dev_dbg(ddev, "skipped %d class/vendor specific "
+ "configuration descriptors\n", n);
+ buffer += i;
+ size -= i;
/* Parse all the interface/altsetting descriptors */
while (size >= sizeof(struct usb_descriptor_header)) {
-------------------------------------------------------
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