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

📄 inode.c

📁 Usb1.1驱动c语言源代码
💻 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.6 2000/03/13 16:44:38 acher Exp $ * *  History: *   0.1  04.01.2000  Created *//*****************************************************************************/#define __NO_VERSION__#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 <asm/uaccess.h>#include "usbdevice_fs.h"/* --------------------------------------------------------------------- */static LIST_HEAD(superlist);struct special {	const char *name;	struct file_operations *fops;	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 struct usb_bus *usbdevfs_findbus(int busnr){        struct list_head *list;        struct usb_bus *bus;        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)                        return bus;        }        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) < 0)			return 0;		filp->f_pos++;		i++;		/* fall through */	case 1:		if (filldir(dirent, "..", 2, i, IROOT) < 0)			return 0;		filp->f_pos++;		i++;		/* fall through */	default:				while (i >= 2 && i < 2+NRSPECIAL) {			spec = &special[filp->f_pos-2];			if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT)) < 0)				return 0;			filp->f_pos++;			i++;		}		if (i < 2+NRSPECIAL)			return 0;		i -= 2+NRSPECIAL;		lock_kernel();		for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {			if (i > 0) {				i--;				continue;			}			bus = list_entry(list, struct usb_bus, bus_list);			sprintf(numbuf, "%03d", bus->busnum);			if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8)) < 0)				break;			filp->f_pos++;		}		unlock_kernel();		return 0;	}}static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct file *filp, void *dirent, filldir_t filldir){	char numbuf[8];	unsigned int i;	if (!dev)		return pos;	sprintf(numbuf, "%03d", dev->devnum);	if (pos > 0)		pos--;	else {		if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff)) < 0)			return -1;		filp->f_pos++;	}	for (i = 0; i < dev->maxchild; i++) {		if (!dev->children[i])			continue;		pos = bus_readdir(dev->children[i], ino, pos, filp, dirent, filldir);		if (pos < 0)

⌨️ 快捷键说明

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