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

📄 usb.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	iface = usb_ifnum_to_if(dev, interface);	if (!iface) {		warn("selecting invalid interface %d", interface);		return -EINVAL;	}	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),	    USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,	    interface, NULL, 0, HZ * 5)) < 0)		return ret;	iface->act_altsetting = alternate;	dev->toggle[0] = 0;	/* 9.1.1.5 says to do this */	dev->toggle[1] = 0;	usb_set_maxpacket(dev);	return 0;}int usb_set_configuration(struct usb_device *dev, int configuration){	int i, ret;	struct usb_config_descriptor *cp = NULL;		for (i=0; i<dev->descriptor.bNumConfigurations; i++) {		if (dev->config[i].bConfigurationValue == configuration) {			cp = &dev->config[i];			break;		}	}	if (!cp) {		warn("selecting invalid configuration %d", configuration);		return -EINVAL;	}	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),	    USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * SET_TIMEOUT)) < 0)		return ret;	dev->actconfig = cp;	dev->toggle[0] = 0;	dev->toggle[1] = 0;	usb_set_maxpacket(dev);	return 0;}int usb_get_report(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_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,		(type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);}int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,		(type << 8) + id, ifnum, buf, size, HZ);}int usb_get_configuration(struct usb_device *dev){	int result;	unsigned int cfgno, length;	unsigned char buffer[8];	unsigned char *bigbuffer;	struct usb_config_descriptor *desc =		(struct usb_config_descriptor *)buffer;	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;	}	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, &dev->config[cfgno], bigbuffer);		if (result > 0)			dbg("descriptor data left");		else if (result < 0) {			result = -EINVAL;			goto err;		}	}	return 0;err:	dev->descriptor.bNumConfigurations = cfgno;	return result;}/* * usb_string: *	returns string length (> 0) or error (< 0) */int usb_string(struct usb_device *dev, int index, char *buf, size_t size){	unsigned char *tbuf;	int err;	unsigned int u, idx;	if (size <= 0 || !buf || !index)		return -EINVAL;	buf[0] = 0;	tbuf = kmalloc(256, GFP_KERNEL);	if (!tbuf)		return -ENOMEM;	/* get langid for strings if it's not yet known */	if (!dev->have_langid) {		err = usb_get_string(dev, 0, 0, tbuf, 4);		if (err < 0) {			err("error getting string descriptor 0 (error=%d)", err);			goto errout;		} else if (tbuf[0] < 4) {			err("string descriptor 0 too short");			err = -EINVAL;			goto errout;		} else {			dev->have_langid = -1;			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);				/* always use the first langid listed */			dbg("USB device number %d default language ID 0x%x",				dev->devnum, dev->string_langid);		}	}	/*	 * Just ask for a maximum length string and then take the length	 * that was returned.	 */	err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);	if (err < 0)		goto errout;	size--;		/* leave room for trailing NULL char in output buffer */	for (idx = 0, u = 2; u < err; u += 2) {		if (idx >= size)			break;		if (tbuf[u+1])			/* high byte */			buf[idx++] = '?';  /* non-ASCII character */		else			buf[idx++] = tbuf[u];	}	buf[idx] = 0;	err = idx; errout:	kfree(tbuf);	return err;}/* * By the time we get here, the device has gotten a new device ID * and is in the default state. We need to identify the thing and * get the ball rolling.. * * Returns 0 for success, != 0 for error. */int usb_new_device(struct usb_device *dev){	int err;	/* USB v1.1 5.5.3 */	/* We read the first 8 bytes from the device descriptor to get to */	/*  the bMaxPacketSize0 field. Then we set the maximum packet size */	/*  for the control pipe, and retrieve the rest */	dev->epmaxpacketin [0] = 8;	dev->epmaxpacketout[0] = 8;	err = usb_set_address(dev);	if (err < 0) {		err("USB device not accepting new address=%d (error=%d)",			dev->devnum, err);		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);		dev->devnum = -1;		return 1;	}	wait_ms(10);	/* Let the SET_ADDRESS settle */	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);	if (err < 8) {		if (err < 0)			err("USB device not responding, giving up (error=%d)", err);		else			err("USB device descriptor short read (expected %i, got %i)", 8, err);		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);		dev->devnum = -1;		return 1;	}	dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;	err = usb_get_device_descriptor(dev);	if (err < sizeof(dev->descriptor)) {		if (err < 0)			err("unable to get device descriptor (error=%d)", err);		else			err("USB device descriptor short read (expected %i, got %i)",				sizeof(dev->descriptor), err);			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);		dev->devnum = -1;		return 1;	}	err = usb_get_configuration(dev);	if (err < 0) {		err("unable to get device %d configuration (error=%d)",			dev->devnum, err);		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);		dev->devnum = -1;		usb_free_dev(dev);		return 1;	}	/* we set the default configuration here */	err = usb_set_configuration(dev, dev->config[0].bConfigurationValue);	if (err) {		err("failed to set device %d default configuration (error=%d)",			dev->devnum, err);		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);		dev->devnum = -1;		return 1;	}	dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d",		dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);#ifdef DEBUG	if (dev->descriptor.iManufacturer)		usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);	if (dev->descriptor.iProduct)		usb_show_string(dev, "Product", dev->descriptor.iProduct);	if (dev->descriptor.iSerialNumber)		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);#endif	/* now that the basic setup is over, add a /proc/bus/usb entry */	usbdevfs_add_device(dev);	/* find drivers willing to handle this device */	usb_find_drivers(dev);	/* userspace may load modules and/or configure further */	call_policy ("add", dev);	return 0;}static int usb_open(struct inode * inode, struct file * file){	int minor = MINOR(inode->i_rdev);	struct usb_driver *c = usb_minors[minor/16];	int err = -ENODEV;	struct file_operations *old_fops, *new_fops = NULL;	/*	 * No load-on-demand? Randy, could you ACK that it's really not	 * supposed to be done?					-- AV	 */	if (!c || !(new_fops = fops_get(c->fops)))		return err;	old_fops = file->f_op;	file->f_op = new_fops;	/* Curiouser and curiouser... NULL ->open() as "no device" ? */	if (file->f_op->open)		err = file->f_op->open(inode,file);	if (err) {		fops_put(file->f_op);		file->f_op = fops_get(old_fops);	}	fops_put(old_fops);	return err;}static struct file_operations usb_fops = {	owner:		THIS_MODULE,	open:		usb_open,};int usb_major_init(void){	if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {		err("unable to get major %d for usb devices", USB_MAJOR);		return -EBUSY;	}	usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);	return 0;}void usb_major_cleanup(void){	devfs_unregister(usb_devfs_handle);	devfs_unregister_chrdev(USB_MAJOR, "usb");}#ifdef CONFIG_PROC_FSstruct list_head *usb_driver_get_list(void){	return &usb_driver_list;}struct list_head *usb_bus_get_list(void){	return &usb_bus_list;}#endif/* * Init */static int __init usb_init(void){	usb_major_init();	usbdevfs_init();	usb_hub_init();	return 0;}/* * Cleanup */static void __exit usb_exit(void){	usb_major_cleanup();	usbdevfs_cleanup();	usb_hub_cleanup();}module_init(usb_init);module_exit(usb_exit);/* * USB may be built into the kernel or be built as modules. * If the USB core [and maybe a host controller driver] is built * into the kernel, and other device drivers are built as modules, * then these symbols need to be exported for the modules to use. */EXPORT_SYMBOL(usb_ifnum_to_if);EXPORT_SYMBOL(usb_epnum_to_ep_desc);EXPORT_SYMBOL(usb_register);EXPORT_SYMBOL(usb_deregister);EXPORT_SYMBOL(usb_scan_devices);EXPORT_SYMBOL(usb_alloc_bus);EXPORT_SYMBOL(usb_free_bus);EXPORT_SYMBOL(usb_register_bus);EXPORT_SYMBOL(usb_deregister_bus);EXPORT_SYMBOL(usb_alloc_dev);EXPORT_SYMBOL(usb_free_dev);EXPORT_SYMBOL(usb_inc_dev_use);EXPORT_SYMBOL(usb_driver_claim_interface);EXPORT_SYMBOL(usb_interface_claimed);EXPORT_SYMBOL(usb_driver_release_interface);EXPORT_SYMBOL(usb_match_id);EXPORT_SYMBOL(usb_root_hub_string);EXPORT_SYMBOL(usb_new_device);EXPORT_SYMBOL(usb_reset_device);EXPORT_SYMBOL(usb_connect);EXPORT_SYMBOL(usb_disconnect);EXPORT_SYMBOL(usb_check_bandwidth);EXPORT_SYMBOL(usb_claim_bandwidth);EXPORT_SYMBOL(usb_release_bandwidth);EXPORT_SYMBOL(usb_set_address);EXPORT_SYMBOL(usb_get_descriptor);EXPORT_SYMBOL(usb_get_class_descriptor);EXPORT_SYMBOL(__usb_get_extra_descriptor);EXPORT_SYMBOL(usb_get_device_descriptor);EXPORT_SYMBOL(usb_get_string);EXPORT_SYMBOL(usb_string);EXPORT_SYMBOL(usb_get_protocol);EXPORT_SYMBOL(usb_set_protocol);EXPORT_SYMBOL(usb_get_report);EXPORT_SYMBOL(usb_set_report);EXPORT_SYMBOL(usb_set_idle);EXPORT_SYMBOL(usb_clear_halt);EXPORT_SYMBOL(usb_set_interface);EXPORT_SYMBOL(usb_get_configuration);EXPORT_SYMBOL(usb_set_configuration);EXPORT_SYMBOL(usb_get_current_frame_number);EXPORT_SYMBOL(usb_alloc_urb);EXPORT_SYMBOL(usb_free_urb);EXPORT_SYMBOL(usb_submit_urb);EXPORT_SYMBOL(usb_unlink_urb);EXPORT_SYMBOL(usb_control_msg);EXPORT_SYMBOL(usb_bulk_msg);EXPORT_SYMBOL(usb_devfs_handle);

⌨️ 快捷键说明

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