config.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 572 行 · 第 1/2 页

C
572
字号
	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, "		    "using maximum allowed: %d\n",		    cfgno, nintf, USB_MAXINTERFACES);		nintf = USB_MAXINTERFACES;	}	/* Go through the descriptors, checking their length and counting the	 * number of altsettings for each interface */	n = 0;	for ((buffer2 = buffer, size2 = size);	      size2 > 0;	     (buffer2 += header->bLength, size2 -= header->bLength)) {		if (size2 < sizeof(struct usb_descriptor_header)) {			dev_warn(ddev, "config %d descriptor has %d excess "			    "byte%s, ignoring\n",			    cfgno, size2, plural(size2));			break;		}		header = (struct usb_descriptor_header *) buffer2;		if ((header->bLength > size2) || (header->bLength < 2)) {			dev_warn(ddev, "config %d has an invalid descriptor "			    "of length %d, skipping remainder of the config\n",			    cfgno, header->bLength);			break;		}		if (header->bDescriptorType == USB_DT_INTERFACE) {			struct usb_interface_descriptor *d;			int inum;			d = (struct usb_interface_descriptor *) header;			if (d->bLength < USB_DT_INTERFACE_SIZE) {				dev_warn(ddev, "config %d has an invalid "				    "interface descriptor of length %d, "				    "skipping\n", cfgno, d->bLength);				continue;			}			inum = d->bInterfaceNumber;			if (inum >= nintf_orig)				dev_warn(ddev, "config %d has an invalid "				    "interface number: %d but max is %d\n",				    cfgno, inum, nintf_orig - 1);			/* Have we already encountered this interface?			 * Count its altsettings */			for (i = 0; i < n; ++i) {				if (inums[i] == inum)					break;			}			if (i < n) {				if (nalts[i] < 255)					++nalts[i];			} else if (n < USB_MAXINTERFACES) {				inums[n] = inum;				nalts[n] = 1;				++n;			}		} else if (header->bDescriptorType == USB_DT_DEVICE ||			    header->bDescriptorType == USB_DT_CONFIG)			dev_warn(ddev, "config %d contains an unexpected "			    "descriptor of type 0x%X, skipping\n",			    cfgno, header->bDescriptorType);	}	/* for ((buffer2 = buffer, size2 = size); ...) */	size = buffer2 - buffer;	config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);	if (n != nintf)		dev_warn(ddev, "config %d has %d interface%s, different from "		    "the descriptor's value: %d\n",		    cfgno, n, plural(n), nintf_orig);	else if (n == 0)		dev_warn(ddev, "config %d has no interfaces?\n", cfgno);	config->desc.bNumInterfaces = nintf = n;	/* Check for missing interface numbers */	for (i = 0; i < nintf; ++i) {		for (j = 0; j < nintf; ++j) {			if (inums[j] == i)				break;		}		if (j >= nintf)			dev_warn(ddev, "config %d has no interface number "			    "%d\n", cfgno, i);	}	/* Allocate the usb_interface_caches and altsetting arrays */	for (i = 0; i < nintf; ++i) {		j = nalts[i];		if (j > USB_MAXALTSETTING) {			dev_warn(ddev, "too many alternate settings for "			    "config %d interface %d: %d, "			    "using maximum allowed: %d\n",			    cfgno, inums[i], j, USB_MAXALTSETTING);			nalts[i] = j = USB_MAXALTSETTING;		}		len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;		config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);		if (!intfc)			return -ENOMEM;		kref_init(&intfc->ref);	}	/* 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 descriptor%s after %s\n",		    n, plural(n), "configuration");	buffer += i;	size -= i;	/* Parse all the interface/altsetting descriptors */	while (size > 0) {		retval = usb_parse_interface(ddev, cfgno, config,		    buffer, size, inums, nalts);		if (retval < 0)			return retval;		buffer += retval;		size -= retval;	}	/* Check for missing altsettings */	for (i = 0; i < nintf; ++i) {		intfc = config->intf_cache[i];		for (j = 0; j < intfc->num_altsetting; ++j) {			for (n = 0; n < intfc->num_altsetting; ++n) {				if (intfc->altsetting[n].desc.				    bAlternateSetting == j)					break;			}			if (n >= intfc->num_altsetting)				dev_warn(ddev, "config %d interface %d has no "				    "altsetting %d\n", cfgno, inums[i], j);		}	}	return 0;}// hub-only!! ... and only exported for reset/reinit path.// otherwise used internally on disconnect/destroy pathvoid usb_destroy_configuration(struct usb_device *dev){	int c, i;	if (!dev->config)		return;	if (dev->rawdescriptors) {		for (i = 0; i < dev->descriptor.bNumConfigurations; i++)			kfree(dev->rawdescriptors[i]);		kfree(dev->rawdescriptors);		dev->rawdescriptors = NULL;	}	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {		struct usb_host_config *cf = &dev->config[c];		kfree(cf->string);		for (i = 0; i < cf->desc.bNumInterfaces; i++) {			if (cf->intf_cache[i])				kref_put(&cf->intf_cache[i]->ref, 					  usb_release_interface_cache);		}	}	kfree(dev->config);	dev->config = NULL;}// 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){	struct device *ddev = &dev->dev;	int ncfg = dev->descriptor.bNumConfigurations;	int result = -ENOMEM;	unsigned int cfgno, length;	unsigned char *buffer;	unsigned char *bigbuffer; 	struct usb_config_descriptor *desc;	if (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) {		dev_err(ddev, "no configurations\n");		return -EINVAL;	}	length = ncfg * sizeof(struct usb_host_config);	dev->config = kzalloc(length, GFP_KERNEL);	if (!dev->config)		goto err2;	length = ncfg * sizeof(char *);	dev->rawdescriptors = kzalloc(length, GFP_KERNEL);	if (!dev->rawdescriptors)		goto err2;	buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);	if (!buffer)		goto err2;	desc = (struct usb_config_descriptor *)buffer;	for (cfgno = 0; cfgno < ncfg; cfgno++) {		/* We grab just the first descriptor so we know how long		 * the whole configuration is */		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,		    buffer, USB_DT_CONFIG_SIZE);		if (result < 0) {			dev_err(ddev, "unable to read config index %d "			    "descriptor/%s\n", cfgno, "start");			dev_err(ddev, "chopping to %d config(s)\n", cfgno);			dev->descriptor.bNumConfigurations = cfgno;			break;		} else if (result < 4) {			dev_err(ddev, "config index %d descriptor too short "			    "(expected %i, got %i)\n", cfgno,			    USB_DT_CONFIG_SIZE, result);			result = -EINVAL;			goto err;		}		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) {			result = -ENOMEM;			goto err;		}		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,		    bigbuffer, length);		if (result < 0) {			dev_err(ddev, "unable to read config index %d "			    "descriptor/%s\n", cfgno, "all");			kfree(bigbuffer);			goto err;		}		if (result < length) {			dev_warn(ddev, "config index %d descriptor too short "			    "(expected %i, got %i)\n", cfgno, length, result);			length = result;		}		dev->rawdescriptors[cfgno] = bigbuffer;		result = usb_parse_configuration(&dev->dev, cfgno,		    &dev->config[cfgno], bigbuffer, length);		if (result < 0) {			++cfgno;			goto err;		}	}	result = 0;err:	kfree(buffer);	dev->descriptor.bNumConfigurations = cfgno;err2:	if (result == -ENOMEM)		dev_err(ddev, "out of memory\n");	return result;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?