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

📄 inode.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	gadget_for_each_ep (ep, dev->gadget) {		struct ep_data	*data;		data = kmalloc (sizeof *data, GFP_KERNEL);		if (!data)			goto enomem;		memset (data, 0, sizeof data);		data->state = STATE_EP_DISABLED;		init_MUTEX (&data->lock);		init_waitqueue_head (&data->wait);		strncpy (data->name, ep->name, sizeof (data->name) - 1);		atomic_set (&data->count, 1);		data->dev = dev;		get_dev (dev);		data->ep = ep;		ep->driver_data = data;		data->req = usb_ep_alloc_request (ep, GFP_KERNEL);		if (!data->req)			goto enomem;		data->inode = gadgetfs_create_file (dev->sb, data->name,				data, &ep_config_operations,				&data->dentry);		if (!data->inode) {			kfree (data);			goto enomem;		}		list_add_tail (&data->epfiles, &dev->epfiles);	}	return 0;enomem:	DBG (dev, "%s enomem\n", __FUNCTION__);	destroy_ep_files (dev);	return -ENOMEM;}static voidgadgetfs_unbind (struct usb_gadget *gadget){	struct dev_data		*dev = get_gadget_data (gadget);	DBG (dev, "%s\n", __FUNCTION__);	spin_lock_irq (&dev->lock);	dev->state = STATE_DEV_UNBOUND;	spin_unlock_irq (&dev->lock);	destroy_ep_files (dev);	gadget->ep0->driver_data = NULL;	set_gadget_data (gadget, NULL);	/* we've already been disconnected ... no i/o is active */	if (dev->req)		usb_ep_free_request (gadget->ep0, dev->req);	DBG (dev, "%s done\n", __FUNCTION__);	put_dev (dev);}static struct dev_data		*the_device;static intgadgetfs_bind (struct usb_gadget *gadget){	struct dev_data		*dev = the_device;	if (!dev)		return -ESRCH;	if (0 != strcmp (CHIP, gadget->name)) {		printk (KERN_ERR "%s expected %s controller not %s\n",			shortname, CHIP, gadget->name);		return -ENODEV;	}	set_gadget_data (gadget, dev);	dev->gadget = gadget;	gadget->ep0->driver_data = dev;	dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;	/* preallocate control response and buffer */	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);	if (!dev->req)		goto enomem;	dev->req->context = NULL;	dev->req->complete = epio_complete;	if (activate_ep_files (dev) < 0)		goto enomem;	INFO (dev, "bound to %s driver\n", gadget->name);	dev->state = STATE_UNCONNECTED;	get_dev (dev);	return 0;enomem:	gadgetfs_unbind (gadget);	return -ENOMEM;}static voidgadgetfs_disconnect (struct usb_gadget *gadget){	struct dev_data		*dev = get_gadget_data (gadget);	if (dev->state == STATE_UNCONNECTED) {		DBG (dev, "already unconnected\n");		return;	}	dev->state = STATE_UNCONNECTED;	INFO (dev, "disconnected\n");	spin_lock (&dev->lock);	next_event (dev, GADGETFS_DISCONNECT);	ep0_readable (dev);	spin_unlock (&dev->lock);}static voidgadgetfs_suspend (struct usb_gadget *gadget){	struct dev_data		*dev = get_gadget_data (gadget);	INFO (dev, "suspended from state %d\n", dev->state);	spin_lock (&dev->lock);	switch (dev->state) {	case STATE_SETUP:		// VERY odd... host died??	case STATE_CONNECTED:	case STATE_UNCONNECTED:		next_event (dev, GADGETFS_SUSPEND);		ep0_readable (dev);		/* FALLTHROUGH */	default:		break;	}	spin_unlock (&dev->lock);}static struct usb_gadget_driver gadgetfs_driver = {#ifdef	HIGHSPEED	.speed		= USB_SPEED_HIGH,#else	.speed		= USB_SPEED_FULL,#endif	.function	= (char *) driver_desc,	.bind		= gadgetfs_bind,	.unbind		= gadgetfs_unbind,	.setup		= gadgetfs_setup,	.disconnect	= gadgetfs_disconnect,	.suspend	= gadgetfs_suspend,	.driver 	= {		.name		= (char *) shortname,		// .shutdown = ...		// .suspend = ...		// .resume = ...	},};/*----------------------------------------------------------------------*/static void gadgetfs_nop(struct usb_gadget *arg) { }static int gadgetfs_probe (struct usb_gadget *gadget){	CHIP = gadget->name;	return -EISNAM;}static struct usb_gadget_driver probe_driver = {	.speed		= USB_SPEED_HIGH,	.bind		= gadgetfs_probe,	.unbind		= gadgetfs_nop,	.setup		= (void *)gadgetfs_nop,	.disconnect	= gadgetfs_nop,	.driver 	= {		.name		= "nop",	},};/* DEVICE INITIALIZATION * *     fd = open ("/dev/gadget/$CHIP", O_RDWR) *     status = write (fd, descriptors, sizeof descriptors) * * That write establishes the device configuration, so the kernel can * bind to the controller ... guaranteeing it can handle enumeration * at all necessary speeds.  Descriptor order is: * * . message tag (u32, host order) ... for now, must be zero; it *	would change to support features like multi-config devices * . full/low speed config ... all wTotalLength bytes (with interface, *	class, altsetting, endpoint, and other descriptors) * . high speed config ... all descriptors, for high speed operation; * 	this one's optional except for high-speed hardware * . device descriptor * * Endpoints are not yet enabled. Drivers may want to immediately * initialize them, using the /dev/gadget/ep* files that are available * as soon as the kernel sees the configuration, or they can wait * until device configuration and interface altsetting changes create * the need to configure (or unconfigure) them. * * After initialization, the device stays active for as long as that * $CHIP file is open.  Events may then be read from that descriptor, * such configuration notifications.  More complex drivers will handle * some control requests in user space. */static int is_valid_config (struct usb_config_descriptor *config){	return config->bDescriptorType == USB_DT_CONFIG		&& config->bLength == USB_DT_CONFIG_SIZE		&& config->bConfigurationValue != 0		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;	/* FIXME if gadget->is_otg, _must_ include an otg descriptor */	/* FIXME check lengths: walk to end */}static ssize_tdev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr){	struct dev_data		*dev = fd->private_data;	ssize_t			value = len, length = len;	unsigned		total;	u32			tag;	char			*kbuf;	if (dev->state != STATE_OPENED)		return -EEXIST;	if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))		return -EINVAL;	/* we might need to change message format someday */	if (copy_from_user (&tag, buf, 4))		return -EFAULT;	if (tag != 0)		return -EINVAL;	buf += 4;	length -= 4;	kbuf = kmalloc (length, SLAB_KERNEL);	if (!kbuf)		return -ENOMEM;	if (copy_from_user (kbuf, buf, length)) {		kfree (kbuf);		return -EFAULT;	}	spin_lock_irq (&dev->lock);	value = -EINVAL;	if (dev->buf)		goto fail;	dev->buf = kbuf;	/* full or low speed config */	dev->config = (void *) kbuf;	total = le16_to_cpup (&dev->config->wTotalLength);	if (!is_valid_config (dev->config) || total >= length)		goto fail;	kbuf += total;	length -= total;	/* optional high speed config */	if (kbuf [1] == USB_DT_CONFIG) {		dev->hs_config = (void *) kbuf;		total = le16_to_cpup (&dev->hs_config->wTotalLength);		if (!is_valid_config (dev->hs_config) || total >= length)			goto fail;		kbuf += total;		length -= total;	}	/* could support multiple configs, using another encoding! */	/* device descriptor (tweaked for paranoia) */	if (length != USB_DT_DEVICE_SIZE)		goto fail;	dev->dev = (void *)kbuf;	if (dev->dev->bLength != USB_DT_DEVICE_SIZE			|| dev->dev->bDescriptorType != USB_DT_DEVICE			|| dev->dev->bNumConfigurations != 1)		goto fail;	dev->dev->bNumConfigurations = 1;	dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200);	/* triggers gadgetfs_bind(); then we can enumerate. */	spin_unlock_irq (&dev->lock);	value = usb_gadget_register_driver (&gadgetfs_driver);	if (value != 0) {		kfree (dev->buf);		dev->buf = NULL;	} else {		/* at this point "good" hardware has for the first time		 * let the USB the host see us.  alternatively, if users		 * unplug/replug that will clear all the error state.		 *		 * note:  everything running before here was guaranteed		 * to choke driver model style diagnostics.  from here		 * on, they can work ... except in cleanup paths that		 * kick in after the ep0 descriptor is closed.		 */		fd->f_op = &ep0_io_operations;		value = len;	}	return value;fail:	spin_unlock_irq (&dev->lock);	pr_debug ("%s: %s fail %Zd, %p\n", shortname, __FUNCTION__, value, dev);	kfree (dev->buf);	dev->buf = NULL;	return value;}static intdev_open (struct inode *inode, struct file *fd){	struct dev_data		*dev = inode->u.generic_ip;	int			value = -EBUSY;	if (dev->state == STATE_DEV_DISABLED) {		dev->ev_next = 0;		dev->state = STATE_OPENED;		fd->private_data = dev;		get_dev (dev);		value = 0;	}	return value;}static struct file_operations dev_init_operations = {	.owner =	THIS_MODULE,	.llseek =	no_llseek,	.open =		dev_open,	.write =	dev_config,	.fasync =	ep0_fasync,	.ioctl =	dev_ioctl,	.release =	dev_release,};/*----------------------------------------------------------------------*//* FILESYSTEM AND SUPERBLOCK OPERATIONS * * Mounting the filesystem creates a controller file, used first for * device configuration then later for event monitoring. *//* FIXME PAM etc could set this security policy without mount options * if epfiles inherited ownership and permissons from ep0 ... */static unsigned default_uid;static unsigned default_gid;static unsigned default_perm = S_IRUSR | S_IWUSR;module_param (default_uid, uint, 0644);module_param (default_gid, uint, 0644);module_param (default_perm, uint, 0644);static struct inode *gadgetfs_make_inode (struct super_block *sb,		void *data, struct file_operations *fops,		int mode){	struct inode *inode = new_inode (sb);	if (inode) {		inode->i_mode = mode;		inode->i_uid = default_uid;		inode->i_gid = default_gid;		inode->i_blksize = PAGE_CACHE_SIZE;		inode->i_blocks = 0;		inode->i_atime = inode->i_mtime = inode->i_ctime				= CURRENT_TIME;		inode->u.generic_ip = data;		inode->i_fop = fops;	}	return inode;}/* creates in fs root directory, so non-renamable and non-linkable. * so inode and dentry are paired, until device reconfig. */static struct inode *gadgetfs_create_file (struct super_block *sb, char const *name,		void *data, struct file_operations *fops,		struct dentry **dentry_p){	struct dentry	*dentry;	struct inode	*inode;	dentry = d_alloc_name(sb->s_root, name);	if (!dentry)		return NULL;	inode = gadgetfs_make_inode (sb, data, fops,			S_IFREG | (default_perm & S_IRWXUGO));	if (!inode) {		dput(dentry);		return NULL;	}	d_add (dentry, inode);	*dentry_p = dentry;	return inode;}static struct super_operations gadget_fs_operations = {	.statfs =	simple_statfs,	.drop_inode =	generic_delete_inode,};static intgadgetfs_fill_super (struct super_block *sb, void *opts, int silent){	struct inode	*inode;	struct dentry	*d;	struct dev_data	*dev;	if (the_device)		return -ESRCH;	/* fake probe to determine $CHIP */	(void) usb_gadget_register_driver (&probe_driver);	if (!CHIP)		return -ENODEV;	/* superblock */	sb->s_blocksize = PAGE_CACHE_SIZE;	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;	sb->s_magic = GADGETFS_MAGIC;	sb->s_op = &gadget_fs_operations;	sb->s_time_gran = 1;	/* root inode */	inode = gadgetfs_make_inode (sb,			NULL, &simple_dir_operations,			S_IFDIR | S_IRUGO | S_IXUGO);	if (!inode)		return -ENOMEM;	inode->i_op = &simple_dir_inode_operations;	if (!(d = d_alloc_root (inode))) {		iput (inode);		return -ENOMEM;	}	sb->s_root = d;	/* the ep0 file is named after the controller we expect;	 * user mode code can use it for sanity checks, like we do.	 */	dev = dev_new ();	if (!dev)		return -ENOMEM;	dev->sb = sb;	if (!(inode = gadgetfs_create_file (sb, CHIP,				dev, &dev_init_operations,				&dev->dentry))) {		put_dev(dev);		return -ENOMEM;	}	/* other endpoint files are available after hardware setup,	 * from binding to a controller.	 */	the_device = dev;	return 0;}/* "mount -t gadgetfs path /dev/gadget" ends up here */static struct super_block *gadgetfs_get_sb (struct file_system_type *t, int flags,		const char *path, void *opts){	return get_sb_single (t, flags, opts, gadgetfs_fill_super);}static voidgadgetfs_kill_sb (struct super_block *sb){	kill_litter_super (sb);	if (the_device) {		put_dev (the_device);		the_device = NULL;	}}/*----------------------------------------------------------------------*/static struct file_system_type gadgetfs_type = {	.owner		= THIS_MODULE,	.name		= shortname,	.get_sb		= gadgetfs_get_sb,	.kill_sb	= gadgetfs_kill_sb,};/*----------------------------------------------------------------------*/static int __init init (void){	int status;	status = register_filesystem (&gadgetfs_type);	if (status == 0)		pr_info ("%s: %s, version " DRIVER_VERSION "\n",			shortname, driver_desc);	return status;}module_init (init);static void __exit cleanup (void){	pr_debug ("unregister %s\n", shortname);	unregister_filesystem (&gadgetfs_type);}module_exit (cleanup);

⌨️ 快捷键说明

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