Hello All
Can anybody tell me what steps i follow to 
write usb driver for ADC card. I have seen
Mouse driver, and it is a bit difficult for
me to design ADC driver based on this.
Can any one will suggest me some solution.
Thanks
Pankaj.

On Tue, 11 Dec 2001 [EMAIL PROTECTED] wrote :
> Send linux-usb-devel mailing list submissions to
>       [EMAIL PROTECTED]
> 
> To subscribe or unsubscribe via the World Wide Web, 
> visit
>       https://lists.sourceforge.net/lists/listinfo/linux-usb--
> devel
> or, via email, send a message with subject or body 
> 'help' to
>       [EMAIL PROTECTED]
> 
> You can reach the person managing the list at
>       [EMAIL PROTECTED]
> 
> When replying, please edit your Subject line so it is 
> more specific
> than "Re: Contents of linux-usb-devel digest..."
> 
> 
> Today's Topics:
> 
>    1. Re: Re: Q: device(file) permissions for USB 
> (Johannes Erdfelt)
>    2. Newbie developer issues (Steven Toth)
>    3. Re: Newbie developer issues (Georg Acher)
>    4. Re: Newbie developer issues (Steven Toth)
>    5. Re: EZUSB firmware uploader, clone or share? 
> (Oliver Neukum)
>    6. [RFC] usbfs patch to use the vfs better (Greg KH)
>    7. Re: [RFC] usbfs patch to use the vfs better 
> (David Brownell)
> 
> --__--__--
> 
> Message: 1
> Date: Mon, 10 Dec 2001 15:03:13 -0500
> From: Johannes Erdfelt <[EMAIL PROTECTED]>
> To: David Brownell <[EMAIL PROTECTED]>
> Cc: Dan Streetman <[EMAIL PROTECTED]>,
>   [EMAIL PROTECTED]
> Subject: Re: [linux-usb-devel] Re: Q: device(file) 
> permissions for USB
> 
> On Mon, Dec 10, 2001, David Brownell 
> <[EMAIL PROTECTED]> wrote:
> > > I also never advocated removing topology 
> information. We already have it
> > > via an ioctl call. I just don't want topology 
> exposed in the directory
> > > structure for usbdevfs.
> > > 
> > > In that case, we're forcing the information on 
> everyone if they care or
> > > not, and most programs don't care.
> > 
> > Hmm ... today we force "addressing information" on 
> everyone regardless
> > of whether they care, and unlike topology info it's 
> quite useless.
> 
> Not really. We use addressing information to provide 
> unique filenames.
> 
> I don't parse the filename, nor should anyone else.
> 
> It could be completely random for all I care, as long 
> as it's unique.
> 
> > For backwards compatibility, I think "usbdevfs" 
> should likely not change
> > very much.  I can imagine replacing "bus number" with 
> a stable ID (like
> > PCI slot/function), and "bus address" with a 
> different one (encoding
> > topology without new directory names).  Adding more 
> directory structure
> > would seem trouble-prone to me.
> 
> I'm against a new directory structure.
> 
> We could encode the topology in the filename, but I 
> don't see why we
> should go through that trouble.
> 
> > But I could imagine something else working a lot 
> better than "usbdevfs".
> > It's just "preliminary" after all, and now folk have 
> had a chance to learn
> > a lot more about how to expose USB to user mode 
> drivers.  There's
> > no reason not to leverage that knowledge to create a 
> better model.
> 
> I agree that we can make it better, but I don't think 
> exposing the
> topology in the directory or filename is better.
> 
> I just think we're focusing on the wrong thing here.
> 
> JE
> 
> 
> 
> --__--__--
> 
> Message: 2
> Reply-To: [EMAIL PROTECTED]
> From: "Steven Toth" <[EMAIL PROTECTED]>
> To: [EMAIL PROTECTED]
> Date: Mon, 10 Dec 2001 20:27:30 +0000
> Subject: [linux-usb-devel] Newbie developer issues
> 
> Hi,
> 
> I'm stuck on a project and I wondered if any of you 
> kind chaps might be able 
> to help? (platform = kernel 2.4.16 using usb-uhci)
> 
> I'm writing a device driver (GPL) for the PrimaScan 
> icam320 webcam (based on 
> the existing driver for dabusb). I'm using sniffusb 
> 0.13 to intercept the 
> windows<->webcam. I've got the device registered, 
> probed and initialised by 
> sending the same control messages logged by sniff usb.
> 
> Now problems or errors until now.
> 
> 
> Question 1. I'm submitting the ISO tranfer URBs which 
> are all coming back 
> (via completion handler) with the correct number of 
> packets - but they are 
> all empty. No errors, status is fine, frame count is 
> increasing as expected 
> ... just no data. What's the best way to prove 100% 
> that they're coming from 
> the webcam? I'll happily patch the kernel to output 
> extra diagnostics if 
> necessary... Any suggestions?
> 
> Example hexdump from received packet data:
> 000000 00ff 0000 0000 0000 0000 0000 0000 0000
> 000010 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 000380 00ff 0000 0000 0000 0000 0000 0000 0000
> 000390 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 000700 00ff 0000 0000 0000 0000 0000 0000 0000
> 000710 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 000a80 00ff 0000 0000 0000 0000 0000 0000 0000
> 000a90 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 000e00 00ff 0000 0000 0000 0000 0000 0000 0000
> 000e10 0000 0000 0000 0000 0000 0000 0000 0000
> *
> 001180 00ff 0000 0000 0000 0000 0000 0000 0000
> 001190 0000 0000 0000 0000 0000 0000 0000 0000
> 
> Question 2. Before the URB is passed to the completion 
> handler, the urb->dev 
> field is being nullified. What's the rational behind 
> this? It causes 
> dabusb.c to oops when calling "unsigned int pipe = 
> usb_rcvisocpipe 
> (purb->dev, _DABUSB_ISOPIPE);" Anyone else noticed 
> this? Look like the 
> driver in 2.4.16 is broke an no one noticed.
> 
> Question 3. SniffUSB starts the logfile with the output 
> below, am I correct 
> in assuming that this is the same as...
> 
> usb_set_configuration (usbdev, usbdev->config[0]
> .bConfigurationValue)
> and
> usb_set_interface (s->usbdev, 0, 6);
> 
> 
> UsbSnoop - IRP_MJ_INTERNAL_DEVICE_CONTROL, 
> IOCTL_INTERNAL_USB_SUBMIT_URB
> 
> >>>>>>>URB 782 going down...
> -- URB_FUNCTION_SELECT_INTERFACE:
> !!! Hdr.Length is wrong! (is: 32, should be at least: 
> 56)
>   ConfigurationHandle     = 0xc2a122c0
>   Interface: Length            = 0x00000024
>   Interface: InterfaceNumber   = 0x00
>   Interface: AlternateSetting  = 0x06
>   Interface: Class             = 0xff
>   Interface: SubClass          = 0x00
>   Interface: Protocol          = 0x00
>   Interface: InterfaceHandle   = 0xcc5ed5f0
>   Interface: NumberOfPipes     = 0x00000001
> 
> <<<<<<< URB 782 coming back...
> -- URB_FUNCTION_SELECT_INTERFACE:
> !!! Hdr.Length is wrong! (is: 32, should be at least: 
> 56)
>   ConfigurationHandle     = 0xc2a122c0
>   Interface: Length            = 0x00000024
>   Interface: InterfaceNumber   = 0x00
>   Interface: AlternateSetting  = 0x06
>   Interface: Class             = 0xff
>   Interface: SubClass          = 0x00
>   Interface: Protocol          = 0x00
>   Interface: InterfaceHandle   = 0xcc5e9d80
>   Interface: NumberOfPipes     = 0x00000001
>   Interface: Pipes[0] : MaximumPacketSize = 0x0380
>   Interface: Pipes[0] : EndpointAddress   = 0x81
>   Interface: Pipes[0] : Interval          = 0x01
>   Interface: Pipes[0] : PipeType          = 0x01 
> (UsbdPipeTypeIsochronous)
>   Interface: Pipes[0] : PipeHandle        = 0xcc5e9d98
>   Interface: Pipes[0] : MaxTransferSize   = 0x00008000
>   Interface: Pipes[0] : PipeFlags         = 0x00
> UsbSnoop - IRP_MJ_INTERNAL_DEVICE_CONTROL, 
> IOCTL_INTERNAL_USB_SUBMIT_URB
> 
> I know you're all busy but any advise/comments would be 
> very welcome.
> 
> Thanks again,
> 
> Steve
> 
> 
> ________________________________________________________-
> _________
> Get your FREE download of MSN Explorer at 
> http://explorer.msn.com/intl.asp
> 
> 
> 
> --__--__--
> 
> Message: 3
> Date: Mon, 10 Dec 2001 22:07:48 +0100
> From: Georg Acher <[EMAIL PROTECTED]>
> To: [EMAIL PROTECTED]
> Subject: Re: [linux-usb-devel] Newbie developer issues
> 
> On Mon, Dec 10, 2001 at 08:27:30PM +0000, Steven Toth 
> wrote:
>  
> > Question 1. I'm submitting the ISO tranfer URBs which 
> are all coming back 
> > (via completion handler) with the correct number of 
> packets - but they are 
> > all empty. No errors, status is fine, frame count is 
> increasing as expected 
> > ... just no data. What's the best way to prove 100% 
> that they're coming from 
> > the webcam? I'll happily patch the kernel to output 
> extra diagnostics if 
> > necessary... Any suggestions?
> 
> Fill the memory with another pattern (eg. 0xaa or such)
> . If it is changed,
> it definitely came from the device. Another hint would 
> be the length of each
> frame.
>  
> > Question 2. Before the URB is passed to the 
> completion handler, the urb->dev 
> > field is being nullified. What's the rational behind 
> this? It causes 
> 
> There's a potential race how to distinguish when an URB 
> is definitely
> finished by the HCD. The nulled ->dev prohibits 
> immediate resubmission for
> example.
> 
> > dabusb.c to oops when calling "unsigned int pipe = 
> usb_rcvisocpipe 
> > (purb->dev, _DABUSB_ISOPIPE);" Anyone else noticed 
> this? Look like the 
> > driver in 2.4.16 is broke an no one noticed.
> 
> The dabusb-driver wasn't updated for a long time, since 
> the device also
> wasn't (commercially) available (at that time...). 
> Since Terratec now starts
> to sell the DR-Box-1 (their name of the receiver), it 
> will get an update soon.
> The current dabusb.c can be found in our CVS at 
> http://usb.cs.tum.edu/
> 
> > Question 3. SniffUSB starts the logfile with the 
> output below, am I correct 
> > in assuming that this is the same as...
> > 
> > usb_set_configuration (usbdev, usbdev->config[0]
> .bConfigurationValue)
> > and
> > usb_set_interface (s->usbdev, 0, 6);
> 
> I'm not familiar with SniffUSB...
> -- 
>          Georg Acher, [EMAIL PROTECTED]         
>          http://www.in.tum.de/~acher/
>           "Oh no, not again !" The bowl of petunias     
>      
> 
> 
> --__--__--
> 
> Message: 4
> Reply-To: [EMAIL PROTECTED]
> From: "Steven Toth" <[EMAIL PROTECTED]>
> To: [EMAIL PROTECTED]
> Subject: Re: [linux-usb-devel] Newbie developer issues
> Date: Mon, 10 Dec 2001 21:44:35 +0000
> 
> 
> Georg, thanks for the feedback....
> 
> >Fill the memory with another pattern (eg. 0xaa or such)
> . If it
> >is changed, it definitely came from the device. 
> Another hint
> >would be the length of each frame.
> 
> Sorry, my fault, I should I said, I already tried that 
> but I'm still getting 
> zero's (indicating that the device is indeed sending 
> them). The length is 
> also good. To be honest, I think the frames are OK, 
> probably me being 
> anal... I wanted to double/triple check the results.
> 
> >
> > > Question 2. Before the URB is passed to the 
> completion handler, the 
> >urb->dev
> > > field is being nullified. What's the rational 
> behind this? It causes
> >
> >There's a potential race how to distinguish when an 
> URB is definitely
> >finished by the HCD. The nulled ->dev prohibits 
> immediate resubmission for
> >example.
> 
> Ok, that makes sense. I went though 20 oops's before I 
> installed kmsgdump 
> and found out why. :-)
> 
> >
> > > dabusb.c to oops when calling "unsigned int pipe = 
> usb_rcvisocpipe
> > > (purb->dev, _DABUSB_ISOPIPE);" Anyone else noticed 
> this? Look like the
> > > driver in 2.4.16 is broke an no one noticed.
> >
> >The dabusb-driver wasn't updated for a long time, 
> since the device also
> >wasn't (commercially) available (at that time...). 
> Since Terratec now 
> >starts
> >to sell the DR-Box-1 (their name of the receiver), it 
> will get an update 
> >soon.
> >The current dabusb.c can be found in our CVS at 
> http://usb.cs.tum.edu/
> >
> > > Question 3. SniffUSB starts the logfile with the 
> output below, am I 
> >correct
> > > in assuming that this is the same as...
> > >
> > > usb_set_configuration (usbdev, usbdev->config[0]
> .bConfigurationValue)
> > > and
> > > usb_set_interface (s->usbdev, 0, 6);
> >
> >I'm not familiar with SniffUSB...
> 
> Thanks anyway,
> 
> Steve
> 
> ________________________________________________________-
> _________
> Get your FREE download of MSN Explorer at 
> http://explorer.msn.com/intl.asp
> 
> 
> 
> --__--__--
> 
> Message: 5
> From: [EMAIL PROTECTED] (Oliver Neukum)
> Reply-To: [EMAIL PROTECTED]
> To: David Brownell <[EMAIL PROTECTED]>
> Subject: Re: [linux-usb-devel] EZUSB firmware uploader, 
> clone or share?
> Date: Tue, 11 Dec 2001 00:00:25 +0100
> Cc: [EMAIL PROTECTED]
> 
> Am Montag, 10. Dezember 2001 18:41 schrieb David 
> Brownell:
> > When "struct usb_device" gets suspend/resume methods,
> > wouldn't such a device just turn its suspend() into a 
> disconnect
> > so it gets fully re-enumerated on a resume()?
> >
> > - Dave
> 
> Firstly, with current device names you must not do so 
> or you could
> find your devices rearranged on resume.
> Secondly, even if you did so, it wouldn't matter, as 
> the device still
> exists as far as the block layer is concerned.
> To reload firmware on a rw block device you simply must 
> allocate
> memory only with GFP_NOIO. Thus if you want to do it in 
> user space
> you must have a demon running which mlocks everything 
> relevant.
> You cannot simply run a shell script on resume.
> 
>       Regards
>               Oliver
> 
> 
> --__--__--
> 
> Message: 6
> Date: Mon, 10 Dec 2001 15:37:16 -0800
> From: Greg KH <[EMAIL PROTECTED]>
> To: [EMAIL PROTECTED]
> Subject: [linux-usb-devel] [RFC] usbfs patch to use the 
> vfs better
> 
> Hi all,
> 
> Here's a patch that converts the usbfs code to use the 
> vfs layer much
> better.  The code is based on pcihpfs, driverfs, and 
> ramfs which all are
> very simple filesystems.  It ends up reducing much of 
> the code, and
> finally the "special" files are easier to understand 
> how they are
> created :)  It also removes lots of BKL accesses, and 
> removes the
> usbdevice_fs entries from the inode and super_block 
> kernel structures.
> 
> I've tested this out with usbview and lsusb, which are 
> the only programs
> that I have that use the filesystem.  Could people with 
> devices that
> access the filesystem (like gphoto2 and other libusb 
> based programs)
> please test this out and let me know if I've broken 
> anything?
> 
> I know I don't have the mount permissions correct right 
> now, but I will
> fix that before submitting the patch to Linus.
> 
> thanks,
> 
> greg k-h
> 
> 
> diff -Nru a/drivers/usb/devio.c b/drivers/usb/devio.c
> --- a/drivers/usb/devio.c     Mon Dec 10 15:24:23 2001
> +++ b/drivers/usb/devio.c     Mon Dec 10 15:24:23 2001
> @@ -471,9 +471,7 @@
>        */
>       lock_kernel();
>       ret = -ENOENT;
> -     if (ITYPE(inode->i_ino) != IDEVICE)
> -             goto out;
> -     dev = inode->u.usbdev_i.p.dev;
> +     dev = inode->u.generic_ip;
>       if (!dev)
>               goto out;
>       ret = -ENOMEM;
> diff -Nru a/drivers/usb/inode.c b/drivers/usb/inode.c
> --- a/drivers/usb/inode.c     Mon Dec 10 15:24:24 2001
> +++ b/drivers/usb/inode.c     Mon Dec 10 15:24:24 2001
> @@ -41,128 +41,19 @@
>  #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 struct super_operations usbfs_ops;
> +static struct address_space_operations usbfs_aops;
> +static struct file_operations usbfs_dir_operations;
> +static struct file_operations default_file_operations;
> +static struct inode_operations 
> usbfs_dir_inode_operations;
> +static struct vfsmount *usbfs_mount;
> +static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
> +static int mount_count = 0;
> +
> +static struct dentry *devices_dentry;
> +static struct dentry *drivers_dentry;
> +static int num_buses;
>  
>  static int parse_options(struct super_block *s, char 
> *data)
>  {
> @@ -242,6 +133,7 @@
>               }
>       }
>  
> +/*
>       s->u.usbdevfs_sb.devuid = devuid;
>       s->u.usbdevfs_sb.devgid = devgid;
>       s->u.usbdevfs_sb.devmode = devmode;
> @@ -251,461 +143,541 @@
>       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)
> +
> +/* -----------------------------------------------------
> ----------------- */
> +
> +static struct dentry *usbfs_lookup (struct inode *dir, 
> struct dentry *dentry)
>  {
> -        struct list_head *list;
> -        struct usb_bus *bus;
> +     d_add(dentry, NULL);
> +     return NULL;
> +}
>  
> -     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;
> +static int usbfs_statfs(struct super_block *sb, struct 
> statfs *buf)
> +{
> +        buf->f_type = USBDEVICE_SUPER_MAGIC;
> +        buf->f_bsize = PAGE_CACHE_SIZE;
> +        buf->f_namelen = NAME_MAX;
> +        return 0;
> +}
> +
> +static struct inode *usbfs_get_inode (struct 
> super_block *sb, int mode, int dev)
> +{
> +     struct inode *inode = new_inode(sb);
> +
> +     if (inode) {
> +             inode->i_mode = mode;
> +             inode->i_uid = current->fsuid;
> +             inode->i_gid = current->fsgid;
> +             inode->i_blksize = PAGE_CACHE_SIZE;
> +             inode->i_blocks = 0;
> +             inode->i_rdev = NODEV;
> +             inode->i_mapping->a_ops = &usbfs_aops;
> +             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_operations;
> +                     break;
> +             case S_IFDIR:
> +                     inode->i_op = &usbfs_dir_inode_operations;
> +                     inode->i_fop = &usbfs_dir_operations;
> +                     break;
>               }
> -        }
> -     up (&usb_bus_list_lock);
> -        return NULL;
> +     }
> +     return inode; 
>  }
>  
> -#if 0
> -static struct usb_device *finddev(struct usb_device 
> *dev, int devnr)
> +static int usbfs_mknod (struct inode *dir, struct 
> dentry *dentry, int mode, int dev)
>  {
> -        unsigned int i;
> -        struct usb_device *d2;
> +     struct inode *inode = usbfs_get_inode(dir->i_sb, mode,
>  dev);
> +     int error = -ENOSPC;
>  
> -        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;
> +     if (inode) {
> +             d_instantiate(dentry, inode);
> +             dget(dentry);
> +             error = 0;
> +     }
> +     return error;
>  }
>  
> -static struct usb_device *usbdevfs_finddevice(struct 
> usb_bus *bus, int devnr)
> +static int usbfs_mkdir (struct inode *dir, struct 
> dentry *dentry, int mode)
>  {
> -        return finddev(bus->root_hub, devnr);
> +     return usbfs_mknod (dir, dentry, mode | S_IFDIR, 0);
>  }
> -#endif
>  
> -/* -----------------------------------------------------
> ----------------- */
> +static int usbfs_create (struct inode *dir, struct 
> dentry *dentry, int mode)
> +{
> +     return usbfs_mknod (dir, dentry, mode | S_IFREG, 0);
> +}
>  
> -static int usbdevfs_revalidate(struct dentry *dentry, 
> int flags)
> +static int usbfs_link (struct dentry *old_dentry, 
> struct inode *dir,
> +                    struct dentry *dentry)
>  {
> -     struct inode *inode = dentry->d_inode;
> +     struct inode *inode = old_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;
> +     if(S_ISDIR(inode->i_mode))
> +             return -EPERM;
> +
> +     inode->i_nlink++;
> +     atomic_inc(&inode->i_count);
> +     dget(dentry);
> +     d_instantiate(dentry, inode);
> +     return 0;
>  }
>  
> -static struct dentry_operations 
> usbdevfs_dentry_operations = {
> -     d_revalidate:   usbdevfs_revalidate,
> -};
> +static inline int usbfs_positive (struct dentry 
> *dentry)
> +{
> +     return dentry->d_inode && !d_unhashed(dentry);
> +}
>  
> -static struct dentry *usbdevfs_root_lookup(struct 
> inode *dir, struct dentry *dentry)
> +static int usbfs_empty (struct dentry *dentry)
>  {
> -     int busnr;
> -     unsigned long ino = 0;
> -     unsigned int i;
> -     struct inode *inode;
> +     struct list_head *list;
>  
> -     /* 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;
> +     spin_lock(&dcache_lock);
> +
> +     list_for_each(list, &dentry->d_subdirs) {
> +             struct dentry *de = list_entry(list, struct dentry, 
> d_child);
> +             if (usbfs_positive(de)) {
> +                     spin_unlock(&dcache_lock);
> +                     return 0;
> +             }
>       }
> -     d_add(dentry, inode);
> -     return NULL;
> +
> +     spin_unlock(&dcache_lock);
> +     return 1;
>  }
>  
> -static struct dentry *usbdevfs_bus_lookup(struct inode 
> *dir, struct dentry *dentry)
> +static int usbfs_unlink (struct inode *dir, struct 
> dentry *dentry)
>  {
> -     struct inode *inode;
> -     int devnr;
> +     int error = -ENOTEMPTY;
>  
> -     /* 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;
> +     if (usbfs_empty(dentry)) {
> +             struct inode *inode = dentry->d_inode;
> +
> +             inode->i_nlink--;
> +             dput(dentry);
> +             error = 0;
>       }
> -     d_add(dentry, inode);
> -     return NULL;
> +     return error;
>  }
>  
> -static int usbdevfs_root_readdir(struct file *filp, 
> void *dirent, filldir_t filldir)
> +static int usbfs_rename (struct inode *old_dir, struct 
> dentry *old_dentry,
> +                      struct inode *new_dir, struct dentry *new_dentry)
>  {
> -     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;
> -             filp->f_pos++;
> -             i++;
> -             /* fall through */
> +     int error = -ENOTEMPTY;
>  
> -     case 1:
> -             if (filldir(dirent, "..", 2, i, IROOT, DT_DIR) < 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), DT_UNKNOWN) < 0)
> -                             return 0;
> -                     filp->f_pos++;
> -                     i++;
> +     if (usbfs_empty(new_dentry)) {
> +             struct inode *inode = new_dentry->d_inode;
> +             if (inode) {
> +                     inode->i_nlink--;
> +                     dput(new_dentry);
>               }
> -             if (i < 2+NRSPECIAL)
> -                     return 0;
> -             i -= 2+NRSPECIAL;
> -             down (&usb_bus_list_lock);
> -             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), DT_UNKNOWN) < 0)
> -                             break;
> -                     filp->f_pos++;
> -             }
> -             up (&usb_bus_list_lock);
> -             return 0;
> +             error = 0;
>       }
> +     return error;
>  }
>  
> -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), DT_UNKNOWN) < 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)
> -                     return -1;
> -     }
> -     return pos;
> -}
> -
> -static int usbdevfs_bus_readdir(struct file *filp, 
> void *dirent, filldir_t filldir)
> -{
> -     struct inode *inode = filp->f_dentry->d_inode;
> -     unsigned long ino = inode->i_ino;
> -     struct usb_bus *bus;
> -
> -     /* sanity check */
> -     if (ITYPE(ino) != IBUS)
> -             return -EINVAL;
> -     switch ((unsigned int)filp->f_pos) {
> -     case 0:
> -             if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR)
>  < 0)
> -                     return 0;
> -             filp->f_pos++;
> -             /* fall through */
> +#define usbfs_rmdir usbfs_unlink
>  
> -     case 1:
> -             if (filldir(dirent, "..", 2, filp->f_pos, IROOT, 
> DT_DIR) < 0)
> -                     return 0;
> -             filp->f_pos++;
> -             /* fall through */
> +/* default file operations */
> +static ssize_t default_read_file (struct file *file, 
> char *buf, size_t count, loff_t *ppos)
> +{
> +     return 0;
> +}
> +
> +static ssize_t default_write_file (struct file *file, 
> const char *buf, size_t count, loff_t *ppos)
> +{
> +     return count;
> +}
> +
> +static loff_t default_file_lseek (struct file *file, 
> loff_t offset, int orig)
> +{
> +     loff_t retval = -EINVAL;
>  
> +     switch(orig) {
> +     case 0:
> +             if (offset > 0) {
> +                     file->f_pos = offset;
> +                     retval = file->f_pos;
> +             } 
> +             break;
> +     case 1:
> +             if ((offset + file->f_pos) > 0) {
> +                     file->f_pos += offset;
> +                     retval = file->f_pos;
> +             } 
> +             break;
>       default:
> -             lock_kernel();
> -             bus = usbdevfs_findbus(IBUSNR(ino));
> -             bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 
> 0xff) << 8), filp->f_pos-2, filp, dirent, filldir);
> -             unlock_kernel();
> -             return 0;
> +             break;
>       }
> +     return retval;
>  }
>  
> -static struct file_operations 
> usbdevfs_root_file_operations = {
> -     readdir: usbdevfs_root_readdir,
> +static int default_open (struct inode *inode, struct 
> file *filp)
> +{
> +     if (inode->u.generic_ip)
> +             filp->private_data = inode->u.generic_ip;
> +
> +     return 0;
> +}
> +
> +static int default_sync_file (struct file *file, 
> struct dentry *dentry, int datasync)
> +{
> +     return 0;
> +}
> +
> +static struct address_space_operations usbfs_aops = {
>  };
>  
> -static struct inode_operations 
> usbdevfs_root_inode_operations = {
> -     lookup: usbdevfs_root_lookup,
> +static struct file_operations usbfs_dir_operations = {
> +     read:           generic_read_dir,
> +     readdir:        dcache_readdir,
> +     fsync:          default_sync_file,
>  };
>  
> -static struct file_operations 
> usbdevfs_bus_file_operations = {
> -     readdir: usbdevfs_bus_readdir,
> +static struct file_operations default_file_operations 
> = {
> +     read:           default_read_file,
> +     write:          default_write_file,
> +     open:           default_open,
> +     llseek:         default_file_lseek,
> +     fsync:          default_sync_file,
> +     mmap:           generic_file_mmap,
>  };
>  
> -static struct inode_operations 
> usbdevfs_bus_inode_operations = {
> -     lookup: usbdevfs_bus_lookup,
> +static struct inode_operations 
> usbfs_dir_inode_operations = {
> +     create:         usbfs_create,
> +     lookup:         usbfs_lookup,
> +     link:           usbfs_link,
> +     unlink:         usbfs_unlink,
> +     mkdir:          usbfs_mkdir,
> +     rmdir:          usbfs_rmdir,
> +     mknod:          usbfs_mknod,
> +     rename:         usbfs_rename,
>  };
>  
> -static void usbdevfs_read_inode(struct inode *inode)
> -{
> -     struct special *spec;
> +static struct super_operations usbfs_ops = {
> +     statfs:         usbfs_statfs,
> +     put_inode:      force_delete,
> +};
>  
> -     inode->i_ctime = inode->i_mtime = inode->i_atime = 
> CURRENT_TIME;
> -     inode->i_mode = S_IFREG;
> -     inode->i_gid = inode->i_uid = 0;
> -     INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
> -     INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
> -     inode->u.usbdev_i.p.dev = NULL;
> -     inode->u.usbdev_i.p.bus = NULL;
> -     switch (ITYPE(inode->i_ino)) {
> -     case ISPECIAL:
> -             if (inode->i_ino == IROOT) {
> -                     inode->i_op = &usbdevfs_root_inode_operations;
> -                     inode->i_fop = &usbdevfs_root_file_operations;
> -                     inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
> -                     return;
> -             }
> -             if (inode->i_ino <= IROOT || inode->i_ino > 
> IROOT+NRSPECIAL)
> -                     return;
> -             spec = &special[inode->i_ino-(IROOT+1)];
> -             inode->i_fop = spec->fops;
> -             return;
> +static struct super_block *usbfs_read_super (struct 
> super_block *sb, void *data, 
> +                                          int silent)
> +{
> +     struct inode *inode;
> +     struct dentry *root;
>  
> -     case IDEVICE:
> -             return;
> +     if (parse_options(sb, data)) {
> +             warn("usbfs: mount parameter error:");
> +             return NULL;
> +     }
>  
> -     case IBUS:
> -             return;
> +     sb->s_blocksize = PAGE_CACHE_SIZE;
> +     sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
> +        sb->s_magic = USBDEVICE_SUPER_MAGIC;
> +     sb->s_op = &usbfs_ops;
> +     inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
>  
> -     default:
> -             return;
> -        }
> -}
> +     if (!inode) {
> +             dbg("%s: could not get inode!\n",__FUNCTION__);
> +             return NULL;
> +     }
>  
> -static void usbdevfs_put_super(struct super_block *sb)
> -{
> -     list_del(&sb->u.usbdevfs_sb.slist);
> -     INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist);
> -     while (!list_empty(&sb->u.usbdevfs_sb.ilist))
> -             free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, 
> struct inode, u.usbdev_i.slist));
> +     root = d_alloc_root(inode);
> +     if (!root) {
> +             dbg("%s: could not get root dentry!\n",__FUNCTION__);
> +             iput(inode);
> +             return NULL;
> +     }
> +     sb->s_root = root;
> +     return sb;
>  }
>  
> -static int usbdevfs_statfs(struct super_block *sb, 
> struct statfs *buf)
> +/**
> + * fs_create_by_name - create a file, given a name
> + * @name:    name of file
> + * @mode:    type of file
> + * @parent:  dentry of directory to create it in
> + * @dentry:  resulting dentry of file
> + *
> + * There is a bit of overhead in creating a file - 
> basically, we 
> + * have to hash the name of the file, then look it up. 
> This will
> + * prevent files of the same name. 
> + * We then call the proper vfs_ function to take care 
> of all the 
> + * file creation details. 
> + * This function handles both regular files and 
> directories.
> + */
> +static int fs_create_by_name (const char *name, mode_t 
> mode,
> +                           struct dentry *parent, struct dentry **dentry)
>  {
> -        buf->f_type = USBDEVICE_SUPER_MAGIC;
> -        buf->f_bsize = PAGE_SIZE/sizeof(long);   /* 
> ??? */
> -        buf->f_bfree = 0;
> -        buf->f_bavail = 0;
> -        buf->f_ffree = 0;
> -        buf->f_namelen = NAME_MAX;
> -        return 0;
> -}
> +     struct dentry *d = NULL;
> +     struct qstr qstr;
> +     int error;
>  
> -static int usbdevfs_remount(struct super_block *s, int 
> *flags, char *data)
> -{
> -     struct list_head *ilist = s->u.usbdevfs_sb.ilist.next;
> -     struct inode *inode;
> -     int ret;
> +     /* 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 (usbfs_mount && usbfs_mount->mnt_sb) {
> +                     parent = usbfs_mount->mnt_sb->s_root;
> +             }
> +     }
>  
> -     if ((ret = parse_options(s, data))) {
> -             printk(KERN_WARNING "usbdevfs: remount parameter 
> error\n");
> -             return ret;
> +     if (!parent) {
> +             dbg("Ah! can not find a parent!\n");
> +             return -EFAULT;
>       }
>  
> -     for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = 
> ilist->next) {
> -             inode = list_entry(ilist, struct inode, 
> u.usbdev_i.slist);
> +     *dentry = NULL;
> +     qstr.name = name;
> +     qstr.len = strlen(name);
> +     qstr.hash = full_name_hash(name,qstr.len);
> +
> +     parent = dget(parent);
> +
> +     down(&parent->d_inode->i_sem);
>  
> -             switch (ITYPE(inode->i_ino)) {
> -                     case ISPECIAL :
> -                             inode->i_uid = s->u.usbdevfs_sb.listuid;
> -                             inode->i_gid = s->u.usbdevfs_sb.listgid;
> -                             inode->i_mode = s->u.usbdevfs_sb.listmode | 
> S_IFREG;
> -                             break;
> -                     case IBUS :
> -                             inode->i_uid = s->u.usbdevfs_sb.busuid;
> -                             inode->i_gid = s->u.usbdevfs_sb.busgid;
> -                             inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR;
> -                             break;
> -                     case IDEVICE :
> -                             inode->i_uid = s->u.usbdevfs_sb.devuid;
> -                             inode->i_gid = s->u.usbdevfs_sb.devgid;
> -                             inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG;
> -                             break;
> +     d = lookup_hash(&qstr,parent);
> +
> +     error = PTR_ERR(d);
> +     if (!IS_ERR(d)) {
> +             switch(mode & S_IFMT) {
> +             case 0: 
> +             case S_IFREG:
> +                     error = vfs_create(parent->d_inode,d,mode);
> +                     break;
> +             case S_IFDIR:
> +                     error = vfs_mkdir(parent->d_inode,d,mode);
> +                     break;
> +             default:
> +                     err("cannot create special files\n");
>               }
> +             *dentry = d;
>       }
> +     up(&parent->d_inode->i_sem);
>  
> -     return 0;
> +     dput(parent);
> +     return error;
>  }
>  
> -static struct super_operations usbdevfs_sops = { 
> -     read_inode:     usbdevfs_read_inode,
> -     put_super:      usbdevfs_put_super,
> -     statfs:         usbdevfs_statfs,
> -     remount_fs:     usbdevfs_remount,
> -};
> -
> -struct super_block *usbdevfs_read_super(struct 
> super_block *s, void *data, int silent)
> +static struct dentry *fs_create_file (const char *name,
>  mode_t mode,
> +                                   struct dentry *parent, void *data,
> +                                   struct file_operations *fops)
>  {
> -        struct inode *root_inode, *inode;
> -     struct list_head *blist;
> -     struct usb_bus *bus;
> -     unsigned int i;
> +     struct dentry *dentry;
> +     int error;
>  
> -     if (parse_options(s, data)) {
> -             printk(KERN_WARNING "usbdevfs: mount parameter 
> error\n");
> -             return NULL;
> +     dbg("creating file '%s'\n",name);
> +
> +     error = fs_create_by_name(name,mode,parent,&dentry);
> +     if (error) {
> +             dentry = NULL;
> +     } else {
> +             if (dentry->d_inode) {
> +                     if (data)
> +                             dentry->d_inode->u.generic_ip = data;
> +                     if (fops)
> +                     dentry->d_inode->i_fop = fops;
> +             }
>       }
>  
> -     /* fill superblock */
> -        s->s_blocksize = 1024;
> -        s->s_blocksize_bits = 10;
> -        s->s_magic = USBDEVICE_SUPER_MAGIC;
> -        s->s_op = &usbdevfs_sops;
> -     INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
> -     INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
> -     root_inode = iget(s, IROOT);
> -        if (!root_inode)
> -                goto out_no_root;
> -        s->s_root = d_alloc_root(root_inode);
> -        if (!s->s_root)
> -                goto out_no_root;
> -     list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
> -     for (i = 0; i < NRSPECIAL; i++) {
> -             if (!(inode = iget(s, IROOT+1+i)))
> -                     continue;
> -             inode->i_uid = s->u.usbdevfs_sb.listuid;
> -             inode->i_gid = s->u.usbdevfs_sb.listgid;
> -             inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG;
> -             special[i].inode = inode;
> -             list_add_tail(&inode->u.usbdev_i.slist, 
> &s->u.usbdevfs_sb.ilist);
> -             list_add_tail(&inode->u.usbdev_i.dlist, &special[i]
> .inodes);
> -     }
> -     down (&usb_bus_list_lock);
> -     for (blist = usb_bus_list.next; blist != 
> &usb_bus_list; blist = blist->next) {
> -             bus = list_entry(blist, struct usb_bus, bus_list);
> -             new_bus_inode(bus, s);
> -             recurse_new_dev_inode(bus->root_hub, s);
> -     }
> -     up (&usb_bus_list_lock);
> -        return s;
> -
> - out_no_root:
> -        printk("usbdevfs_read_super: get root inode 
> failed\n");
> -        iput(root_inode);
> -        return NULL;
> +     return dentry;
> +}
> +
> +static void fs_remove_file (struct dentry *dentry)
> +{
> +     struct dentry *parent = dentry->d_parent;
> +     
> +     if (!parent || !parent->d_inode)
> +             return;
> +
> +     down(&parent->d_inode->i_sem);
> +     if (usbfs_positive(dentry)) {
> +             if (dentry->d_inode) {
> +                     if (S_ISDIR(dentry->d_inode->i_mode))
> +                             vfs_rmdir(parent->d_inode,dentry);
> +                     else
> +                             vfs_unlink(parent->d_inode,dentry);
> +             }
> +
> +             dput(dentry);
> +     }
> +     up(&parent->d_inode->i_sem);
>  }
>  
> +/* -----------------------------------------------------
> ----------------- */
> +
> +
> +
>  /*
> - * The usbdevfs name is now depreciated (as of 2.5.1).
> + * The usbdevfs name is now deprecated (as of 2.5.1).
>   * It will be removed when the 2.7.x development cycle 
> is started.
>   * You have been warned :)
>   */
> -static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", 
> usbdevfs_read_super, FS_SINGLE);
> -static DECLARE_FSTYPE(usb_fs_type, "usbfs", 
> usbdevfs_read_super, FS_SINGLE);
> +static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", 
> usbfs_read_super, FS_SINGLE);
> +static DECLARE_FSTYPE(usb_fs_type, "usbfs", 
> usbfs_read_super, FS_SINGLE);
>  
>  /* -----------------------------------------------------
> ----------------- */
> +static int get_mount (void)
> +{
> +     struct vfsmount *mnt;
> +
> +     spin_lock (&mount_lock);
> +     if (usbfs_mount) {
> +             mntget(usbfs_mount);
> +             ++mount_count;
> +             spin_unlock (&mount_lock);
> +             goto go_ahead;
> +     }
> +
> +     spin_unlock (&mount_lock);
> +     mnt = kern_mount (&usb_fs_type);
> +     if (IS_ERR(mnt)) {
> +             err ("could not mount the fs...erroring out!\n");
> +             return -ENODEV;
> +     }
> +     spin_lock (&mount_lock);
> +     if (!usbfs_mount) {
> +             usbfs_mount = mnt;
> +             ++mount_count;
> +             spin_unlock (&mount_lock);
> +             goto go_ahead;
> +     }
> +     mntget(usbfs_mount);
> +     ++mount_count;
> +     spin_unlock (&mount_lock);
> +     mntput(mnt);
> +
> +go_ahead:
> +     dbg("mount_count = %d\n", mount_count);
> +     return 0;
> +}
> +
> +static void remove_mount (void)
> +{
> +     struct vfsmount *mnt;
> +
> +     spin_lock (&mount_lock);
> +     mnt = usbfs_mount;
> +     --mount_count;
> +     if (!mount_count)
> +             usbfs_mount = NULL;
> +
> +     spin_unlock (&mount_lock);
> +     mntput(mnt);
> +     dbg("mount_count = %d\n", mount_count);
> +}
> +
> +static int create_special_files (void)
> +{
> +     int retval;
> +
> +     /* create the devices and drivers special files */
> +     retval = get_mount ();
> +     if (retval)
> +             return retval;
> +     devices_dentry = fs_create_file ("devices", S_IFREG | 
> S_IRUGO,
> +                                      NULL, NULL, &usbdevfs_devices_fops);
> +     if (devices_dentry == NULL) {
> +             err ("Unable to create devices usbfs file");
> +             return -ENODEV;
> +     }
> +     drivers_dentry = fs_create_file ("drivers", S_IFREG | 
> S_IRUGO,
> +                                      NULL, NULL, &usbdevfs_drivers_fops);
> +     if (drivers_dentry == NULL) {
> +             err ("Unable to create drivers usbfs file");
> +             return -ENODEV;
> +     }
> +
> +     return 0;
> +}
> +
> +static void remove_special_files (void)
> +{
> +     if (devices_dentry)
> +             fs_remove_file (devices_dentry);
> +     if (drivers_dentry)
> +             fs_remove_file (drivers_dentry);
> +     devices_dentry = NULL;
> +     drivers_dentry = NULL;
> +     remove_mount();
> +}
>  
>  static void update_special_inodes (void)
>  {
> -     int i;
> -     for (i = 0; i < NRSPECIAL; i++) {
> -             struct inode *inode = special[i].inode;
> +     struct inode *inode;
> +
> +     if (devices_dentry) {
> +             inode = devices_dentry->d_inode;
> +             if (inode)
> +                     inode->i_atime = inode->i_mtime = inode->i_ctime = 
> CURRENT_TIME;
> +     }
> +     if (drivers_dentry) {
> +             inode = devices_dentry->d_inode;
>               if (inode)
>                       inode->i_atime = inode->i_mtime = inode->i_ctime = 
> CURRENT_TIME;
>       }
>  }
>  
> -
>  void usbdevfs_add_bus(struct usb_bus *bus)
>  {
> -     struct list_head *slist;
> +     char name[8];
> +     int retval;
> +
> +     /* create the special files if this is the first bus 
> added */
> +     if (num_buses == 0) {
> +             retval = create_special_files();
> +             if (retval)
> +                     return;
> +     }
> +     ++num_buses;
> +
> +     sprintf (name, "%03d", bus->busnum);
> +     bus->dentry = fs_create_file (name,
> +                                   S_IFDIR | S_IXUGO | S_IRUGO,
> +                                   NULL, bus, NULL);
> +     if (bus->dentry == NULL)
> +             return;
>  
> -     lock_kernel();
> -     for (slist = superlist.next; slist != &superlist; 
> slist = slist->next)
> -             new_bus_inode(bus, list_entry(slist, struct 
> super_block, u.usbdevfs_sb.slist));
> -     update_special_inodes();
> -     unlock_kernel();
>       usbdevfs_conn_disc_event();
>  }
>  
> +
>  void usbdevfs_remove_bus(struct usb_bus *bus)
>  {
> -     lock_kernel();
> -     while (!list_empty(&bus->inodes))
> -             free_inode(list_entry(bus->inodes.next, struct inode,
>  u.usbdev_i.dlist));
> -     update_special_inodes();
> -     unlock_kernel();
> +     if (bus->dentry) {
> +             fs_remove_file (bus->dentry);
> +             bus->dentry = NULL;
> +     }
> +
> +     --num_buses;
> +     if (num_buses <= 0) {
> +             remove_special_files();
> +             num_buses = 0;
> +     }
> +
>       usbdevfs_conn_disc_event();
>  }
>  
>  void usbdevfs_add_device(struct usb_device *dev)
>  {
> -     struct list_head *slist;
> +     char name[8];
> +
> +     sprintf (name, "%03d", dev->devnum);
> +     dev->dentry = fs_create_file (name,
> +                                   S_IFREG | S_IRUGO | S_IWUSR,
> +                                   dev->bus->dentry, dev,
> +                                   &usbdevfs_device_file_operations);
>  
> -     lock_kernel();
> -     for (slist = superlist.next; slist != &superlist; 
> slist = slist->next)
> -             new_dev_inode(dev, list_entry(slist, struct 
> super_block, u.usbdevfs_sb.slist));
>       update_special_inodes();
> -     unlock_kernel();
>       usbdevfs_conn_disc_event();
>  }
>  
> @@ -715,8 +687,10 @@
>       struct siginfo sinfo;
>  
>       lock_kernel();
> -     while (!list_empty(&dev->inodes))
> -             free_inode(list_entry(dev->inodes.next, struct inode,
>  u.usbdev_i.dlist));
> +     if (dev->dentry) {
> +             fs_remove_file (dev->dentry);
> +             dev->dentry = NULL;
> +     }
>       while (!list_empty(&dev->filelist)) {
>               ds = list_entry(dev->filelist.next, struct dev_state,
>  list);
>               list_del(&ds->list);
> @@ -732,9 +706,8 @@
>                       send_sig_info(ds->discsignr, &sinfo, ds->disctask);
>               }
>       }
> -
> -     update_special_inodes();
>       unlock_kernel();
> +     update_special_inodes();
>       usbdevfs_conn_disc_event();
>  }
>  
> @@ -748,9 +721,6 @@
>  {
>       int ret;
>  
> -     for (ret = 0; ret < NRSPECIAL; ret++) {
> -             INIT_LIST_HEAD(&special[ret].inodes);
> -     }
>       if ((ret = usb_register(&usbdevfs_driver)))
>               return ret;
>       if ((ret = register_filesystem(&usb_fs_type))) {
> @@ -766,6 +736,10 @@
>       /* create mount point for usbdevfs */
>       usbdir = proc_mkdir("usb", proc_bus);
>  #endif       
> +
> +     num_buses = 0;
> +
> +     
>       return ret;
>  }
>  
> diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c
> --- a/drivers/usb/usb.c       Mon Dec 10 15:24:24 2001
> +++ b/drivers/usb/usb.c       Mon Dec 10 15:24:24 2001
> @@ -421,7 +421,6 @@
>       bus->bandwidth_isoc_reqs = 0;
>  
>       INIT_LIST_HEAD(&bus->bus_list);
> -     INIT_LIST_HEAD(&bus->inodes);
>  
>       atomic_set(&bus->refcnt, 1);
>  
> @@ -1016,7 +1015,6 @@
>       dev->bus = bus;
>       dev->parent = parent;
>       atomic_set(&dev->refcnt, 1);
> -     INIT_LIST_HEAD(&dev->inodes);
>       INIT_LIST_HEAD(&dev->filelist);
>  
>       init_MUTEX(&dev->serialize);
> diff -Nru a/include/linux/fs.h b/include/linux/fs.h
> --- a/include/linux/fs.h      Mon Dec 10 15:24:24 2001
> +++ b/include/linux/fs.h      Mon Dec 10 15:24:24 2001
> @@ -312,7 +312,6 @@
>  #include <linux/udf_fs_i.h>
>  #include <linux/ncp_fs_i.h>
>  #include <linux/proc_fs_i.h>
> -#include <linux/usbdev_fs_i.h>
>  #include <linux/jffs2_fs_i.h>
>  #include <linux/cramfs_fs_sb.h>
>  
> @@ -503,7 +502,6 @@
>               struct ncp_inode_info           ncpfs_i;
>               struct proc_inode_info          proc_i;
>               struct socket                   socket_i;
> -             struct usbdev_inode_info        usbdev_i;
>               struct jffs2_inode_info         jffs2_i;
>               void                            *generic_ip;
>       } u;
> @@ -687,7 +685,6 @@
>  #include <linux/bfs_fs_sb.h>
>  #include <linux/udf_fs_sb.h>
>  #include <linux/ncp_fs_sb.h>
> -#include <linux/usbdev_fs_sb.h>
>  #include <linux/cramfs_fs_sb.h>
>  #include <linux/jffs2_fs_sb.h>
>  
> @@ -745,7 +742,6 @@
>               struct bfs_sb_info      bfs_sb;
>               struct udf_sb_info      udf_sb;
>               struct ncp_sb_info      ncpfs_sb;
> -             struct usbdev_sb_info   usbdevfs_sb;
>               struct jffs2_sb_info    jffs2_sb;
>               struct cramfs_sb_info   cramfs_sb;
>               void                    *generic_sbp;
> diff -Nru a/include/linux/usb.h b/include/linux/usb.h
> --- a/include/linux/usb.h     Mon Dec 10 15:24:24 2001
> +++ b/include/linux/usb.h     Mon Dec 10 15:24:24 2001
> @@ -989,8 +989,7 @@
>       int bandwidth_int_reqs;         /* number of Interrupt 
> requesters */
>       int bandwidth_isoc_reqs;        /* number of Isoc. 
> requesters */
>  
> -     /* usbdevfs inode list */
> -     struct list_head inodes;
> +     struct dentry *dentry;          /* usbfs dentry entry for the 
> bus */
>  
>       atomic_t refcnt;
>  };
> @@ -1090,9 +1089,8 @@
>    
>       void *hcpriv;                   /* Host Controller private data */
>       
> -        /* usbdevfs inode list */
> -     struct list_head inodes;
>       struct list_head filelist;
> +     struct dentry *dentry;          /* usbfs dentry entry for the 
> device */
>  
>       /*
>        * Child devices - these can be either new devices
> diff -Nru a/include/linux/usbdevice_fs.h 
> b/include/linux/usbdevice_fs.h
> --- a/include/linux/usbdevice_fs.h    Mon Dec 10 15:24:24 
> 2001
> +++ b/include/linux/usbdevice_fs.h    Mon Dec 10 15:24:24 
> 2001
> @@ -150,17 +150,6 @@
>  #include <linux/list.h>
>  #include <asm/semaphore.h>
>  
> -/*
> - * inode number macros
> - */
> -#define ITYPE(x)   ((x)&(0xf<<28))
> -#define ISPECIAL   (0<<28)
> -#define IBUS       (1<<28)
> -#define IDEVICE    (2<<28)
> -#define IBUSNR(x)  (((x)>>8)&0xff)
> -#define IDEVNR(x)  ((x)&0xff)
> -
> -#define IROOT      1
>  
>  struct dev_state {
>       struct list_head list;      /* state list */
> 
> 
> --__--__--
> 
> Message: 7
> Date: Mon, 10 Dec 2001 15:54:43 -0800
> From: David Brownell <[EMAIL PROTECTED]>
> Subject: Re: [linux-usb-devel] [RFC] usbfs patch to use 
> the vfs better
> To: Greg KH <[EMAIL PROTECTED]>, 
> [EMAIL PROTECTED]
> 
> > I've tested this out with usbview and lsusb, which 
> are the only programs
> > that I have that use the filesystem.  Could people 
> with devices that
> > access the filesystem (like gphoto2 and other libusb 
> based programs)
> > please test this out and let me know if I've broken 
> anything?
> 
> I'll see how this works with jUSB, jPhoto, and such ... 
>  but it'll likely
> take a while to do that.
> 
> To my understanding, jUSB bangs on that filesystem code 
> much
> more than libusb ... :)
> 
> - Dave
> 
> 
> 
> 
> 
> --__--__--
> 
> _______________________________________________
> [EMAIL PROTECTED]
> To unsubscribe, use the last form field at:
> https://lists.sourceforge.net/lists/listinfo/linux-usb-d-
> evel
> 
> 
> End of linux-usb-devel Digest
 


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to