# 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 [EMAIL PROTECTED] 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
_______________________________________________________________
Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas -- http://devcon.sprintpcs.com/adp/index.cfm
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel