diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-03 14:48:52 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-03 14:48:52 -0800 |
commit | e779553185f660ece90347ba849eccdfbdf46d6d (patch) | |
tree | 07c2a021b94f4f00876094f90570fa0df397c603 /bad | |
parent | e449d88200084a27997993b78956a6f2b252f2df (diff) | |
download | patches-e779553185f660ece90347ba849eccdfbdf46d6d.tar.gz |
moved usbfs2.patch into the bad/ dir
Diffstat (limited to 'bad')
-rw-r--r-- | bad/usbfs2.patch | 557 |
1 files changed, 557 insertions, 0 deletions
diff --git a/bad/usbfs2.patch b/bad/usbfs2.patch new file mode 100644 index 0000000000000..92b5d4a5c623f --- /dev/null +++ b/bad/usbfs2.patch @@ -0,0 +1,557 @@ +--- + drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 2 + drivers/usb/usbfs2/Kconfig | 7 + drivers/usb/usbfs2/Makefile | 7 + drivers/usb/usbfs2/inode.c | 485 ++++++++++++++++++++++++++++++++++++++++++++ + include/linux/usb.h | 2 + 6 files changed, 505 insertions(+) + +--- /dev/null ++++ gregkh-2.6/drivers/usb/usbfs2/Makefile +@@ -0,0 +1,7 @@ ++usbfs2-objs := inode.o ++ ++obj-$(CONFIG_USB_USBFS2) += usbfs2.o ++ ++ifeq ($(CONFIG_USB_DEBUG),y) ++EXTRA_CFLAGS += -DDEBUG ++endif +--- gregkh-2.6.orig/drivers/usb/Kconfig ++++ gregkh-2.6/drivers/usb/Kconfig +@@ -77,6 +77,8 @@ config USB + + source "drivers/usb/core/Kconfig" + ++source "drivers/usb/usbfs2/Kconfig" ++ + source "drivers/usb/host/Kconfig" + + source "drivers/usb/ip/Kconfig" +--- gregkh-2.6.orig/drivers/usb/Makefile ++++ gregkh-2.6/drivers/usb/Makefile +@@ -8,6 +8,8 @@ obj-$(CONFIG_USB) += core/ + + obj-$(CONFIG_USB_MON) += mon/ + ++obj-$(CONFIG_USB_USBFS2) += usbfs2/ ++ + obj-$(CONFIG_PCI) += host/ + obj-$(CONFIG_USB_EHCI_HCD) += host/ + obj-$(CONFIG_USB_ISP116X_HCD) += host/ +--- /dev/null ++++ gregkh-2.6/drivers/usb/usbfs2/Kconfig +@@ -0,0 +1,7 @@ ++config USB_USBFS2 ++ tristate "USB device filesystem - version 2" ++ depends on USB ++ ---help--- ++ Select this option to get the usb device file system, mark 2 ++ ++ Most users want to say Y here. +--- /dev/null ++++ gregkh-2.6/drivers/usb/usbfs2/inode.c +@@ -0,0 +1,485 @@ ++/* ++ * usbfs2.c - usbfs2 ++ * ++ * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version ++ * 2 as published by the Free Software Foundation. ++ * ++ * Based on security/inode.c which had the following copyright notice: ++ * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de> ++ */ ++ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/fs.h> ++#include <linux/mount.h> ++#include <linux/pagemap.h> ++#include <linux/init.h> ++#include <linux/namei.h> ++#include <linux/usb.h> ++#include "../core/usb.h" ++ ++#define USBFS2_MAGIC 0x75736266 ++ ++static struct vfsmount *mount; ++static int mount_count; ++ ++/* ++ * TODO: ++ * I think I can get rid of these default_file_ops, but not quite sure... ++ */ ++static ssize_t default_read_file(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ return 0; ++} ++ ++static ssize_t default_write_file(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ return count; ++} ++ ++static int default_open(struct inode *inode, struct file *file) ++{ ++ if (inode->u.generic_ip) ++ file->private_data = inode->u.generic_ip; ++ ++ return 0; ++} ++ ++static struct file_operations default_file_ops = { ++ .read = default_read_file, ++ .write = default_write_file, ++ .open = default_open, ++}; ++ ++static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) ++{ ++ struct inode *inode = new_inode(sb); ++ ++ if (inode) { ++ inode->i_mode = mode; ++ inode->i_uid = 0; ++ inode->i_gid = 0; ++ inode->i_blksize = PAGE_CACHE_SIZE; ++ inode->i_blocks = 0; ++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; ++ switch (mode & S_IFMT) { ++ default: ++ init_special_inode(inode, mode, dev); ++ break; ++ case S_IFREG: ++ inode->i_fop = &default_file_ops; ++ break; ++ case S_IFDIR: ++ inode->i_op = &simple_dir_inode_operations; ++ inode->i_fop = &simple_dir_operations; ++ ++ /* directory inodes start off with i_nlink == 2 (for "." entry) */ ++ inode->i_nlink++; ++ break; ++ } ++ } ++ return inode; ++} ++ ++/* SMP-safe */ ++static int mknod(struct inode *dir, struct dentry *dentry, ++ int mode, dev_t dev) ++{ ++ struct inode *inode; ++ int error = -EPERM; ++ ++ if (dentry->d_inode) ++ return -EEXIST; ++ ++ inode = get_inode(dir->i_sb, mode, dev); ++ if (inode) { ++ d_instantiate(dentry, inode); ++ dget(dentry); ++ error = 0; ++ } ++ return error; ++} ++ ++static int mkdir(struct inode *dir, struct dentry *dentry, int mode) ++{ ++ int res; ++ ++ mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; ++ res = mknod(dir, dentry, mode, 0); ++ if (!res) ++ dir->i_nlink++; ++ return res; ++} ++ ++static int create(struct inode *dir, struct dentry *dentry, int mode) ++{ ++ mode = (mode & S_IALLUGO) | S_IFREG; ++ return mknod(dir, dentry, mode, 0); ++} ++ ++static inline int positive(struct dentry *dentry) ++{ ++ return dentry->d_inode && !d_unhashed(dentry); ++} ++ ++static int fill_super(struct super_block *sb, void *data, int silent) ++{ ++ static struct tree_descr files[] = {{""}}; ++ ++ return simple_fill_super(sb, USBFS2_MAGIC, files); ++} ++ ++static struct super_block *get_sb(struct file_system_type *fs_type, ++ int flags, const char *dev_name, ++ void *data) ++{ ++ return get_sb_single(fs_type, flags, data, fill_super); ++} ++ ++static struct file_system_type fs_type = { ++ .owner = THIS_MODULE, ++ .name = "usbfs2", ++ .get_sb = get_sb, ++ .kill_sb = kill_litter_super, ++}; ++ ++static int create_by_name(const char *name, mode_t mode, ++ struct dentry *parent, ++ struct dentry **dentry) ++{ ++ int error = 0; ++ ++ *dentry = NULL; ++ ++ /* If the parent is not specified, we create it in the root. ++ * We need the root dentry to do this, which is in the super ++ * block. A pointer to that is in the struct vfsmount that we ++ * have around. ++ */ ++ if (!parent ) { ++ if (mount && mount->mnt_sb) { ++ parent = mount->mnt_sb->s_root; ++ } ++ } ++ if (!parent) { ++ pr_debug("usbfs2: Ah! can not find a parent!\n"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&parent->d_inode->i_mutex); ++ *dentry = lookup_one_len(name, parent, strlen(name)); ++ if (!IS_ERR(dentry)) { ++ if ((mode & S_IFMT) == S_IFDIR) ++ error = mkdir(parent->d_inode, *dentry, mode); ++ else ++ error = create(parent->d_inode, *dentry, mode); ++ } else ++ error = PTR_ERR(dentry); ++ mutex_unlock(&parent->d_inode->i_mutex); ++ ++ return error; ++} ++ ++/** ++ * usbfs2_create_file - create a file in the usbfs2 filesystem ++ * ++ * @name: a pointer to a string containing the name of the file to create. ++ * @mode: the permission that the file should have ++ * @parent: a pointer to the parent dentry for this file. This should be a ++ * directory dentry if set. If this paramater is NULL, then the ++ * file will be created in the root of the usbfs2 filesystem. ++ * @data: a pointer to something that the caller will want to get to later ++ * on. The inode.u.generic_ip pointer will point to this value on ++ * the open() call. ++ * @fops: a pointer to a struct file_operations that should be used for ++ * this file. ++ * ++ * This is the basic "create a file" function for usbfs2. It allows for a ++ * wide range of flexibility in createing a file, or a directory (if you ++ * want to create a directory, the usbfs2_create_dir() function is ++ * recommended to be used instead.) ++ * ++ * This function will return a pointer to a dentry if it succeeds. This ++ * pointer must be passed to the usbfs2_remove() function when the file is ++ * to be removed (no automatic cleanup happens if your module is unloaded, ++ * you are responsible here.) If an error occurs, NULL will be returned. ++ * ++ * If usbfs2 is not enabled in the kernel, the value -ENODEV will be ++ * returned. It is not wise to check for this value, but rather, check for ++ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling ++ * code. ++ */ ++static struct dentry *usbfs2_create_file(const char *name, mode_t mode, ++ struct dentry *parent, void *data, ++ struct file_operations *fops) ++{ ++ struct dentry *dentry = NULL; ++ int error; ++ ++ pr_debug("usbfs2: creating file '%s'\n",name); ++ ++ error = simple_pin_fs("usbfs2", &mount, &mount_count); ++ if (error) { ++ dentry = ERR_PTR(error); ++ goto exit; ++ } ++ ++ error = create_by_name(name, mode, parent, &dentry); ++ if (error) { ++ dentry = ERR_PTR(error); ++ simple_release_fs(&mount, &mount_count); ++ goto exit; ++ } ++ ++ if (dentry->d_inode) { ++ if (fops) ++ dentry->d_inode->i_fop = fops; ++ if (data) ++ dentry->d_inode->u.generic_ip = data; ++ } ++exit: ++ return dentry; ++} ++ ++/** ++ * usbfs2_create_dir - create a directory in the usbfs2 filesystem ++ * ++ * @name: a pointer to a string containing the name of the directory to ++ * create. ++ * @parent: a pointer to the parent dentry for this file. This should be a ++ * directory dentry if set. If this paramater is NULL, then the ++ * directory will be created in the root of the usbfs2 filesystem. ++ * ++ * This function creates a directory in usbfs2 with the given name. ++ * ++ * This function will return a pointer to a dentry if it succeeds. This ++ * pointer must be passed to the usbfs2_remove() function when the file is ++ * to be removed (no automatic cleanup happens if your module is unloaded, ++ * you are responsible here.) If an error occurs, NULL will be returned. ++ * ++ * If usbfs2 is not enabled in the kernel, the value -ENODEV will be ++ * returned. It is not wise to check for this value, but rather, check for ++ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling ++ * code. ++ */ ++static struct dentry *usbfs2_create_dir(const char *name, struct dentry *parent) ++{ ++ return usbfs2_create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, ++ parent, NULL, NULL); ++} ++ ++/** ++ * usbfs2_remove - removes a file or directory from the usbfs2 filesystem ++ * ++ * @dentry: a pointer to a the dentry of the file or directory to be ++ * removed. ++ * ++ * This function removes a file or directory in usbfs2 that was previously ++ * created with a call to another usbfs2 function (like ++ * usbfs2_create_file() or variants thereof.) ++ * ++ * This function is required to be called in order for the file to be ++ * removed, no automatic cleanup of files will happen when a module is ++ * removed, you are responsible here. ++ */ ++static void usbfs2_remove(struct dentry *dentry) ++{ ++ struct dentry *parent; ++ ++ if (!dentry) ++ return; ++ ++ parent = dentry->d_parent; ++ if (!parent || !parent->d_inode) ++ return; ++ ++ mutex_lock(&parent->d_inode->i_mutex); ++ if (positive(dentry)) { ++ if (dentry->d_inode) { ++ if (S_ISDIR(dentry->d_inode->i_mode)) ++ simple_rmdir(parent->d_inode, dentry); ++ else ++ simple_unlink(parent->d_inode, dentry); ++ dput(dentry); ++ } ++ } ++ mutex_unlock(&parent->d_inode->i_mutex); ++ simple_release_fs(&mount, &mount_count); ++} ++ ++ ++static void add_bus(struct usb_bus *bus) ++{ ++ struct dentry *parent; ++ char name[8]; ++ ++ sprintf(name, "%03d", bus->busnum); ++ ++ parent = mount->mnt_sb->s_root; ++ bus->usbfs2_dentry = usbfs2_create_dir(name, parent); ++ if (bus->usbfs2_dentry == NULL) { ++ dev_err(bus->controller, "error creating usbfs2 bus entry"); ++ return; ++ } ++} ++ ++static void remove_bus(struct usb_bus *bus) ++{ ++ if (bus->usbfs2_dentry) { ++ usbfs2_remove(bus->usbfs2_dentry); ++ bus->usbfs2_dentry = NULL; ++ } ++} ++ ++struct ep_object { ++ struct usb_endpoint_descriptor *desc; ++ struct usb_device *udev; ++ struct dentry *dentry; ++}; ++ ++static ssize_t ep_read_file(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ep_object *ep_obj = file->private_data; ++ dbg("endpoint %02x read from", ep_obj->desc->bEndpointAddress); ++ return 0; ++} ++ ++static ssize_t ep_write_file(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ep_object *ep_obj = file->private_data; ++ dbg("endpoint %02x written to", ep_obj->desc->bEndpointAddress); ++ return count; ++} ++ ++static int ep_open(struct inode *inode, struct file *file) ++{ ++ if (inode->u.generic_ip) ++ file->private_data = inode->u.generic_ip; ++ return 0; ++} ++ ++static struct file_operations ep_file_ops = { ++ .read = ep_read_file, ++ .write = ep_write_file, ++ .open = ep_open, ++}; ++ ++static void add_endpoint(struct dentry *parent, struct usb_host_endpoint *endpoint, struct usb_device *udev) ++{ ++ struct ep_object *ep_obj; ++ char name[8]; ++ ++ ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); ++ if (!ep_obj) ++ return; ++ ++ ep_obj->desc = &endpoint->desc; ++ ep_obj->udev = udev; ++ ++ sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); ++ ep_obj->dentry = usbfs2_create_file(name, S_IRWXU | S_IRUGO | S_IXUGO, ++ parent, ep_obj, &ep_file_ops); ++} ++ ++static void add_device(struct usb_device *dev) ++{ ++ char name[8]; ++ ++ if (!dev->bus->usbfs2_dentry) { ++ dev_err(&dev->dev, "no directory created for the device's bus\n"); ++ return; ++ } ++ ++ sprintf(name, "%03d", dev->devnum); ++ dev->usbfs2_dentry = usbfs2_create_dir(name, dev->bus->usbfs2_dentry); ++ if (dev->usbfs2_dentry == NULL) { ++ dev_err(&dev->dev, "error creating usbfs2 device entry"); ++ return; ++ } ++ add_endpoint(dev->usbfs2_dentry, &dev->ep0, dev); ++ ++} ++ ++static void remove_device(struct usb_device *dev) ++{ ++ if (dev->usbfs2_dentry) { ++ usbfs2_remove(dev->usbfs2_dentry); ++ dev->usbfs2_dentry = NULL; ++ } ++#if 0 ++ /* FIXME need to do something like this here */ ++ while (!list_empty(&dev->filelist)) { ++ struct dev_state *ds; ++ struct siginfo sinfo; ++ ++ ds = list_entry(dev->filelist.next, struct dev_state, list); ++ wake_up_all(&ds->wait); ++ list_del_init(&ds->list); ++ if (ds->discsignr) { ++ sinfo.si_signo = SIGPIPE; ++ sinfo.si_errno = EPIPE; ++ sinfo.si_code = SI_ASYNCIO; ++ sinfo.si_addr = ds->disccontext; ++ kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid); ++ } ++ } ++#endif ++} ++ ++static int usbfs2_notify(struct notifier_block *self, unsigned long action, ++ void *dev) ++{ ++ switch (action) { ++ case USB_DEVICE_ADD: ++ add_device(dev); ++ break; ++ case USB_DEVICE_REMOVE: ++ remove_device(dev); ++ break; ++ case USB_BUS_ADD: ++ add_bus(dev); ++ break; ++ case USB_BUS_REMOVE: ++ remove_bus(dev); ++ break; ++ } ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block usbfs2_nb = { ++ .notifier_call = usbfs2_notify, ++}; ++ ++ ++static int __init usbfs2_init(void) ++{ ++ int retval; ++ ++ retval = register_filesystem(&fs_type); ++ if (retval) ++ goto exit; ++ ++ usb_register_notify(&usbfs2_nb); ++ ++exit: ++ return retval; ++} ++ ++static void __exit usbfs2_exit(void) ++{ ++ usb_unregister_notify(&usbfs2_nb); ++ simple_release_fs(&mount, &mount_count); ++ unregister_filesystem(&fs_type); ++} ++ ++core_initcall(usbfs2_init); ++module_exit(usbfs2_exit); ++MODULE_LICENSE("GPL"); ++ +--- gregkh-2.6.orig/include/linux/usb.h ++++ gregkh-2.6/include/linux/usb.h +@@ -291,6 +291,7 @@ struct usb_bus { + int bandwidth_isoc_reqs; /* number of Isoc. requests */ + + struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ ++ struct dentry *usbfs2_dentry; /* usbfs2 dentry entry for the bus */ + + struct class_device *class_dev; /* class device for this bus */ + struct kref kref; /* reference counting for this bus */ +@@ -361,6 +362,7 @@ struct usb_device { + struct list_head filelist; + struct class_device *class_dev; + struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ ++ struct dentry *usbfs2_dentry; /* usbfs2 dentry entry for the device */ + + /* + * Child devices - these can be either new devices |