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

Reply via email to