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

📄 usb.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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;}/** * usb_disconnect - disconnect a device (usbcore-internal) * @pdev: pointer to device being disconnected * Context: !in_interrupt () * * Something got disconnected. Get rid of it, and all of its children. * * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. * * This call is synchronous, and may not be used in an interrupt context. */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) {				if (driver->owner)					__MOD_INC_USE_COUNT(driver->owner);				down(&driver->serialize);				driver->disconnect(dev, interface->private_data);				up(&driver->serialize);				if (driver->owner)					__MOD_DEC_USE_COUNT(driver->owner);				/* if driver->disconnect didn't release the interface */				if (interface->driver)					usb_driver_release_interface(driver, interface);			}			/* remove our device node for this interface */			put_device(&interface->dev);		}	}	/* 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);		usbfs_remove_device(dev);		put_device(&dev->dev);	}	/* Free up the device itself */	usb_free_dev(dev);}/** * usb_connect - connects a new device during enumeration (usbcore-internal) * @dev: partially enumerated device * * 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). * * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. */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-)	 * ... it's also called from modprobe/rmmod/apmd threads as part	 * of virtual root hub init/reinit.  In the init case, the hub code 	 * won't have seen this, but not so for reinit ... 	 */	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. */// hub-only!! ... and only exported for reset/reinit path.// otherwise used internally, for usb_new_device()int usb_set_address(struct usb_device *dev){	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,		// FIXME USB_CTRL_SET_TIMEOUT		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);}/** * usb_get_descriptor - issues a generic GET_DESCRIPTOR request * @dev: the device whose descriptor is being retrieved * @type: the descriptor type (USB_DT_*) * @index: the number of the descriptor * @buf: where to put the descriptor * @size: how big is "buf"? * Context: !in_interrupt () * * Gets a USB descriptor.  Convenience functions exist to simplify * getting some types of descriptors.  Use * usb_get_device_descriptor() for USB_DT_DEVICE, * and usb_get_string() or usb_string() for USB_DT_STRING. * Configuration descriptors (USB_DT_CONFIG) are part of the device * structure, at least for the current configuration. * In addition to a number of USB-standard descriptors, some * devices also use class-specific or vendor-specific descriptors. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */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--) {		/* retries if the returned length was 0; flakey device */		if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),				    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,				    (type << 8) + index, 0, buf, size,				    HZ * USB_CTRL_GET_TIMEOUT)) > 0				|| result == -EPIPE)			break;	}	return result;}/** * usb_get_string - gets a string descriptor * @dev: the device whose string descriptor is being retrieved * @langid: code for language chosen (from string descriptor zero) * @index: the number of the descriptor * @buf: where to put the string * @size: how big is "buf"? * Context: !in_interrupt () * * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, * in little-endian byte order). * The usb_string() function will often be a convenient way to turn * these strings into kernel-printable form. * * Strings may be referenced in device, configuration, interface, or other * descriptors, and could also be used in vendor-specific ways. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */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 * USB_CTRL_GET_TIMEOUT);}/** * usb_get_device_descriptor - (re)reads the device descriptor * @dev: the device whose device descriptor is being updated * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, * which dedicates space for this purpose.  Note that several fields are * converted to the host CPU's byte order:  the USB version (bcdUSB), and * vendors product and version fields (idVendor, idProduct, and bcdDevice). * That lets device drivers compare against non-byteswapped constants. * * There's normally no need to use this call, although some devices * will change their descriptors after events like updating firmware. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */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;}/** * usb_get_status - issues a GET_STATUS call * @dev: the device whose status is being checked * @type: USB_RECIP_*; for device, interface, or endpoint * @target: zero (for device), else interface or endpoint number * @data: pointer to two bytes of bitmap data * Context: !in_interrupt () * * Returns device, interface, or endpoint status.  Normally only of * interest to see if the device is self powered, or has enabled the * remote wakeup facility; or whether a bulk or interrupt endpoint * is halted ("stalled"). * * Bits in these status bitmaps are set using the SET_FEATURE request, * and cleared using the CLEAR_FEATURE request.  The usb_clear_halt() * function should be used to clear halt ("stall") status. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */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 * USB_CTRL_GET_TIMEOUT);}// hub-only!! ... and only exported for reset/reinit path.// otherwise used internally, for config/altsetting reconfig.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 {				if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])					dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;			}		}	}}/** * usb_clear_halt - tells device to clear endpoint halt/stall condition * @dev: device whose endpoint is halted * @pipe: endpoint "pipe" being cleared * Context: !in_interrupt () * * This is used to clear halt conditions for bulk and interrupt endpoints, * as reported by URB completion status.  Endpoints that are halted are * sometimes referred to as being "stalled".  Such endpoints are unable * to transmit or receive data until the halt status is cleared.  Any URBs * queued queued for such an endpoint should normally be unlinked before * clearing the halt condition. * * Note that control and isochronous endpoints don't halt, although control * endpoints report "protocol stall" (for unsupported requests) using the * same status code used to report a true stall. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */int usb_clear_halt(struct usb_device *dev, int pipe){	int result;	__u16 status;	unsigned char *buffer;	int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);/*	if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))		return 0;*/	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,		HZ * USB_CTRL_SET_TIMEOUT);	/* don't clear if failed */	if (result < 0)		return result;	buffer = kmalloc(sizeof(status), GFP_KERNEL);	if (!buffer) {		err("unable to allocate memory for configuration descriptors");		return -ENOMEM;	}	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,		// FIXME USB_CTRL_GET_TIMEOUT, yes?  why not usb_get_status() ?		buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);	memcpy(&status, buffer, sizeof(status));	kfree(buffer);	if (result < 0)		return result;	if (le16_to_cpu(status) & 1)		return -EPIPE;		/* still halted */	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));	/* toggle is reset on clear */	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);	return 0;}/** * usb_set_interface - Makes a particular alternate setting be current * @dev: the device whose interface is being updated * @interface: the interface being updated * @alternate: the setting being chosen. * Context: !in_interrupt () * * This is used to enable data transfers on interfaces that may not * be enabled by default.  Not all devices support such configurability. * * Within any given configuration, each interface may have several * alternative settings.  These are often used to control levels of * bandwidth consumption.  For example, the default setting for a high * speed interrupt endpoint may not send more than about 4KBytes per * microframe, and isochronous endpoints may never be part of a an * interface's default setting.  To access such bandwidth, alternate * interface setting must be made current. * * Note that in the Linux USB subsystem, bandwidth associated with * an endpoint in a given alternate setting is not reserved until an * is submitted that needs that bandwidth.  Some other operating systems * allocate bandwidth early, when a configuration is chosen. * * This call is synchronous, and may not be used in an interrupt context. * * Returns zero on success, or else the status code returned by the * underlying usb_control_msg() call. */int usb_set_interface(struct usb_device *dev, int interface, int alternate){	struct usb_interface *iface;	struct usb_interface_descriptor *iface_as;	int i, ret;	iface = usb_ifnum_to_if(dev, interface);	if (!ifa

⌨️ 快捷键说明

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