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

📄 inode.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************//* *	inode.c  --  Inode/Dentry functions for the USB device file system. * *	Copyright (C) 2000 *          Thomas Sailer (sailer@ife.ee.ethz.ch) * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2 of the License, or *	(at your option) any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  $Id: inode.c,v 1.1.1.1 2004/03/25 05:51:21 laputa Exp $ * *  History: *   0.1  04.01.2000  Created *//*****************************************************************************/#define __NO_VERSION__#include <linux/config.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/locks.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/usb.h>#include <linux/usbdevice_fs.h>#include <asm/uaccess.h>/* --------------------------------------------------------------------- *//* * This list of superblocks is still used, * but since usbdevfs became FS_SINGLE * there is only one super_block. */static LIST_HEAD(superlist);struct special {	const char *name;	struct file_operations *fops;	struct inode *inode;	struct list_head inodes;};static struct special special[] = { 	{ "devices", &usbdevfs_devices_fops,  },	{ "drivers", &usbdevfs_drivers_fops,  }};#define NRSPECIAL (sizeof(special)/sizeof(special[0]))/* --------------------------------------------------------------------- */static int dnumber(struct dentry *dentry){	const char *name;	unsigned int s;	if (dentry->d_name.len != 3)		return -1;	name = dentry->d_name.name;	if (name[0] < '0' || name[0] > '9' ||	    name[1] < '0' || name[1] > '9' ||	    name[2] < '0' || name[2] > '9')		return -1;	s = name[0] - '0';	s = s * 10 + name[1] - '0';	s = s * 10 + name[2] - '0';	return s;}/* * utility functions; should be called with the kernel lock held * to protect against busses/devices appearing/disappearing */static void new_dev_inode(struct usb_device *dev, struct super_block *sb){	struct inode *inode;	unsigned int devnum = dev->devnum;	unsigned int busnum = dev->bus->busnum;	if (devnum < 1 || devnum > 127 || busnum > 255)		return;	inode = iget(sb, IDEVICE | (busnum << 8) | devnum);	if (!inode) {		printk(KERN_ERR "usbdevfs: cannot create inode for bus %u device %u\n", busnum, devnum);		return;	}	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;	inode->i_uid = sb->u.usbdevfs_sb.devuid;	inode->i_gid = sb->u.usbdevfs_sb.devgid;	inode->i_mode = sb->u.usbdevfs_sb.devmode | S_IFREG;	inode->i_fop = &usbdevfs_device_file_operations;	inode->i_size = sizeof(struct usb_device_descriptor);	inode->u.usbdev_i.p.dev = dev;	list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);	list_add_tail(&inode->u.usbdev_i.dlist, &dev->inodes);}static void recurse_new_dev_inode(struct usb_device *dev, struct super_block *sb){	unsigned int i;	if (!dev)		return;	new_dev_inode(dev, sb);	for (i = 0; i < dev->maxchild; i++) {                if (!dev->children[i])                        continue;		recurse_new_dev_inode(dev->children[i], sb);	}}static void new_bus_inode(struct usb_bus *bus, struct super_block *sb){	struct inode *inode;	unsigned int busnum = bus->busnum;	if (busnum > 255)		return;	inode = iget(sb, IBUS | (busnum << 8));	if (!inode) {		printk(KERN_ERR "usbdevfs: cannot create inode for bus %u\n", busnum);		return;	}	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;	inode->i_uid = sb->u.usbdevfs_sb.busuid;	inode->i_gid = sb->u.usbdevfs_sb.busgid;	inode->i_mode = sb->u.usbdevfs_sb.busmode | S_IFDIR;	inode->i_op = &usbdevfs_bus_inode_operations;	inode->i_fop = &usbdevfs_bus_file_operations;	inode->u.usbdev_i.p.bus = bus;	list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);	list_add_tail(&inode->u.usbdev_i.dlist, &bus->inodes);}static void free_inode(struct inode *inode){	inode->u.usbdev_i.p.bus = NULL;	inode->u.usbdev_i.p.dev = NULL;	inode->i_mode &= ~S_IRWXUGO;	inode->i_uid = inode->i_gid = 0;	inode->i_size = 0;	list_del(&inode->u.usbdev_i.slist);	INIT_LIST_HEAD(&inode->u.usbdev_i.slist);	list_del(&inode->u.usbdev_i.dlist);	INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);	iput(inode);}static int parse_options(struct super_block *s, char *data){	uid_t devuid = 0, busuid = 0, listuid = 0;	gid_t devgid = 0, busgid = 0, listgid = 0;	umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;	char *curopt = NULL, *value;	/* parse options */	if (data)		curopt = strtok(data, ",");	for (; curopt; curopt = strtok(NULL, ",")) {		if ((value = strchr(curopt, '=')) != NULL)			*value++ = 0;		if (!strcmp(curopt, "devuid")) {			if (!value || !value[0])				return -EINVAL;			devuid = simple_strtoul(value, &value, 0);			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "devgid")) {			if (!value || !value[0])				return -EINVAL;			devgid = simple_strtoul(value, &value, 0);			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "devmode")) {			if (!value || !value[0])				return -EINVAL;			devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "busuid")) {			if (!value || !value[0])				return -EINVAL;			busuid = simple_strtoul(value, &value, 0);			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "busgid")) {			if (!value || !value[0])				return -EINVAL;			busgid = simple_strtoul(value, &value, 0);			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "busmode")) {			if (!value || !value[0])				return -EINVAL;			busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "listuid")) {			if (!value || !value[0])				return -EINVAL;			listuid = simple_strtoul(value, &value, 0);			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "listgid")) {			if (!value || !value[0])				return -EINVAL;			listgid = simple_strtoul(value, &value, 0);			if (*value)				return -EINVAL;		}		if (!strcmp(curopt, "listmode")) {			if (!value || !value[0])				return -EINVAL;			listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;			if (*value)				return -EINVAL;		}	}	s->u.usbdevfs_sb.devuid = devuid;	s->u.usbdevfs_sb.devgid = devgid;	s->u.usbdevfs_sb.devmode = devmode;	s->u.usbdevfs_sb.busuid = busuid;	s->u.usbdevfs_sb.busgid = busgid;	s->u.usbdevfs_sb.busmode = busmode;	s->u.usbdevfs_sb.listuid = listuid;	s->u.usbdevfs_sb.listgid = listgid;	s->u.usbdevfs_sb.listmode = listmode;	return 0;}static struct usb_bus *usbdevfs_findbus(int busnr){        struct list_head *list;        struct usb_bus *bus;	down (&usb_bus_list_lock);        for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {                bus = list_entry(list, struct usb_bus, bus_list);                if (bus->busnum == busnr) {			up (&usb_bus_list_lock);                        return bus;		}        }	up (&usb_bus_list_lock);        return NULL;}#if 0static struct usb_device *finddev(struct usb_device *dev, int devnr){        unsigned int i;        struct usb_device *d2;        if (!dev)                return NULL;        if (dev->devnum == devnr)                return dev;        for (i = 0; i < dev->maxchild; i++) {                if (!dev->children[i])                        continue;                if ((d2 = finddev(dev->children[i], devnr)))                        return d2;        }        return NULL;}static struct usb_device *usbdevfs_finddevice(struct usb_bus *bus, int devnr){        return finddev(bus->root_hub, devnr);}#endif/* --------------------------------------------------------------------- */static int usbdevfs_revalidate(struct dentry *dentry, int flags){	struct inode *inode = dentry->d_inode;        if (!inode)                return 0;	if (ITYPE(inode->i_ino) == IBUS && !inode->u.usbdev_i.p.bus)		return 0;	if (ITYPE(inode->i_ino) == IDEVICE && !inode->u.usbdev_i.p.dev)		return 0;	return 1;}static struct dentry_operations usbdevfs_dentry_operations = {	d_revalidate:	usbdevfs_revalidate,};static struct dentry *usbdevfs_root_lookup(struct inode *dir, struct dentry *dentry){	int busnr;	unsigned long ino = 0;	unsigned int i;	struct inode *inode;	/* sanity check */	if (dir->i_ino != IROOT)		return ERR_PTR(-EINVAL);	dentry->d_op = &usbdevfs_dentry_operations;	busnr = dnumber(dentry);	if (busnr >= 0 && busnr <= 255)		ino = IBUS | (busnr << 8);	if (!ino) {		for (i = 0; i < NRSPECIAL; i++) {			if (strlen(special[i].name) == dentry->d_name.len && 			    !strncmp(special[i].name, dentry->d_name.name, dentry->d_name.len)) {				ino = ISPECIAL | (i + IROOT + 1);				break;			}		}	}	if (!ino)		return ERR_PTR(-ENOENT);	inode = iget(dir->i_sb, ino);	if (!inode)		return ERR_PTR(-EINVAL);	if (inode && ITYPE(ino) == IBUS && inode->u.usbdev_i.p.bus == NULL) {		iput(inode);		inode = NULL;	}	d_add(dentry, inode);	return NULL;}static struct dentry *usbdevfs_bus_lookup(struct inode *dir, struct dentry *dentry){	struct inode *inode;	int devnr;	/* sanity check */	if (ITYPE(dir->i_ino) != IBUS)		return ERR_PTR(-EINVAL);	dentry->d_op = &usbdevfs_dentry_operations;	devnr = dnumber(dentry);	if (devnr < 1 || devnr > 127)		return ERR_PTR(-ENOENT);	inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);	if (!inode)		return ERR_PTR(-EINVAL);	if (inode && inode->u.usbdev_i.p.dev == NULL) {		iput(inode);		inode = NULL;	}	d_add(dentry, inode);	return NULL;}static int usbdevfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir){	struct inode *inode = filp->f_dentry->d_inode;	unsigned long ino = inode->i_ino;	struct special *spec;	struct list_head *list;	struct usb_bus *bus;	char numbuf[8];	unsigned int i;	/* sanity check */	if (ino != IROOT)		return -EINVAL;	i = filp->f_pos;	switch (i) {	case 0:		if (filldir(dirent, ".", 1, i, IROOT, DT_DIR) < 0)			return 0;

⌨️ 快捷键说明

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