⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* 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;}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){	int retval;	for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {		*utf++ = *ascii++ & 0x7f;		*utf++ = 0;	}	return retval;}/* * root_hub_string is used by each host controller's root hub code, * so that they're identified consistently throughout the system. */int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len){	char buf [30];	// assert (len > (2 * (sizeof (buf) + 1)));	// assert (strlen (type) <= 8);	// language ids	if (id == 0) {		*data++ = 4; *data++ = 3;	/* 4 bytes data */		*data++ = 0; *data++ = 0;	/* some language id */		return 4;	// serial number	} else if (id == 1) {		sprintf (buf, "%x", serial);	// product description	} else if (id == 2) {		sprintf (buf, "USB %s Root Hub", type);	// id 3 == vendor description	// unsupported IDs --> "stall"	} else	    return 0;	data [0] = 2 + ascii2utf (buf, data + 2, len - 2);	data [1] = 3;	return data [0];}/* * __usb_get_extra_descriptor() finds a descriptor of specific type in the * extra field of the interface and endpoint descriptor structs. */int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr){	struct usb_descriptor_header *header;	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 (header->bDescriptorType == type) {			*ptr = header;			return 0;		}		buffer += header->bLength;		size -= header->bLength;	}	return -1;}/* * Something got disconnected. Get rid of it, and all of its children. */void usb_disconnect(struct usb_device **pdev){	struct usb_device * dev = *pdev;	int i;	if (!dev)		return;	*pdev = NULL;	info("USB disconnect on device %d", dev->devnum);	if (dev->actconfig) {		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {			struct usb_interface *interface = &dev->actconfig->interface[i];			struct usb_driver *driver = interface->driver;			if (driver) {				down(&driver->serialize);				driver->disconnect(dev, interface->private_data);				up(&driver->serialize);				/* if driver->disconnect didn't release the interface */				if (interface->driver)					usb_driver_release_interface(driver, interface);			}		}	}	/* Free up all the children.. */	for (i = 0; i < USB_MAXCHILDREN; i++) {		struct usb_device **child = dev->children + i;		if (*child)			usb_disconnect(child);	}	/* Let policy agent unload modules etc */	call_policy ("remove", dev);	/* Free the device number and remove the /proc/bus/usb entry */	if (dev->devnum > 0) {		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);		usbdevfs_remove_device(dev);	}	/* Free up the device itself */	usb_free_dev(dev);}/* * Connect a new USB device. This basically just initializes * the USB device information and sets up the topology - it's * up to the low-level driver to reset the port and actually * do the setup (the upper levels don't know how to do that). */void usb_connect(struct usb_device *dev){	int devnum;	// FIXME needs locking for SMP!!	/* why? this is called only from the hub thread, 	 * which hopefully doesn't run on multiple CPU's simultaneously 8-)	 */	dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */#ifndef DEVNUM_ROUND_ROBIN	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);#else	/* round_robin alloc of devnums */	/* Try to allocate the next devnum beginning at bus->devnum_next. */	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);	if (devnum >= 128)		devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);	dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);#endif	/* round_robin alloc of devnums */	if (devnum < 128) {		set_bit(devnum, dev->bus->devmap.devicemap);		dev->devnum = devnum;	}}/* * These are the actual routines to send * and receive control messages. */#ifdef CONFIG_USB_LONG_TIMEOUT#define GET_TIMEOUT 10 #else#define GET_TIMEOUT 3#endif#define SET_TIMEOUT 3int usb_set_address(struct usb_device *dev){	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,		0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT);}int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size){	int i = 5;	int result;		memset(buf,0,size);	// Make sure we parse really received data	while (i--) {		if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,			(type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) > 0 ||		     result == -EPIPE)			break;	/* retry if the returned length was 0; flaky device */	}	return result;}int usb_get_class_descriptor(struct usb_device *dev, int ifnum,		unsigned char type, unsigned char id, void *buf, int size){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,		(type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);}int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,		(USB_DT_STRING << 8) + index, langid, buf, size, HZ * GET_TIMEOUT);}int usb_get_device_descriptor(struct usb_device *dev){	int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,				     sizeof(dev->descriptor));	if (ret >= 0) {		le16_to_cpus(&dev->descriptor.bcdUSB);		le16_to_cpus(&dev->descriptor.idVendor);		le16_to_cpus(&dev->descriptor.idProduct);		le16_to_cpus(&dev->descriptor.bcdDevice);	}	return ret;}int usb_get_status(struct usb_device *dev, int type, int target, void *data){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ * GET_TIMEOUT);}int usb_get_protocol(struct usb_device *dev, int ifnum){	unsigned char type;	int ret;	if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),	    USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,	    0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0)		return ret;	return type;}int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,		protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT);}int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,		(duration << 8) | report_id, ifnum, NULL, 0, HZ * SET_TIMEOUT);}void usb_set_maxpacket(struct usb_device *dev){	int i, b;	for (i=0; i<dev->actconfig->bNumInterfaces; i++) {		struct usb_interface *ifp = dev->actconfig->interface + i;		struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;		struct usb_endpoint_descriptor *ep = as->endpoint;		int e;		for (e=0; e<as->bNumEndpoints; e++) {			b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;			if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==				USB_ENDPOINT_XFER_CONTROL) {	/* Control => bidirectional */				dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;				dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;				}			else if (usb_endpoint_out(ep[e].bEndpointAddress)) {				if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])					dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;			}			else {

⌨️ 快捷键说明

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