~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/usb/inode.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*****************************************************************************/
  2 
  3 /*
  4  *      inode.c  --  Inode/Dentry functions for the USB device file system.
  5  *
  6  *      Copyright (C) 2000
  7  *          Thomas Sailer (sailer@ife.ee.ethz.ch)
  8  *
  9  *      This program is free software; you can redistribute it and/or modify
 10  *      it under the terms of the GNU General Public License as published by
 11  *      the Free Software Foundation; either version 2 of the License, or
 12  *      (at your option) any later version.
 13  *
 14  *      This program is distributed in the hope that it will be useful,
 15  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 16  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17  *      GNU General Public License for more details.
 18  *
 19  *      You should have received a copy of the GNU General Public License
 20  *      along with this program; if not, write to the Free Software
 21  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 22  *
 23  *  $Id: inode.c,v 1.3 2000/01/11 13:58:25 tom Exp $
 24  *
 25  *  History:
 26  *   0.1  04.01.2000  Created
 27  */
 28 
 29 /*****************************************************************************/
 30 
 31 #define __NO_VERSION__
 32 #include <linux/config.h>
 33 #include <linux/module.h>
 34 #include <linux/fs.h>
 35 #include <linux/sched.h>
 36 #include <linux/smp_lock.h>
 37 #include <linux/locks.h>
 38 #include <linux/init.h>
 39 #include <linux/proc_fs.h>
 40 #include <linux/usb.h>
 41 #include <linux/usbdevice_fs.h>
 42 #include <asm/uaccess.h>
 43 
 44 /* --------------------------------------------------------------------- */
 45 
 46 static LIST_HEAD(superlist);
 47 
 48 struct special {
 49         const char *name;
 50         struct file_operations *fops;
 51         struct inode *inode;
 52         struct list_head inodes;
 53 };
 54 
 55 static struct special special[] = { 
 56         { "devices", &usbdevfs_devices_fops,  },
 57         { "drivers", &usbdevfs_drivers_fops,  }
 58 };
 59 
 60 #define NRSPECIAL (sizeof(special)/sizeof(special[0]))
 61 
 62 /* --------------------------------------------------------------------- */
 63 
 64 static int dnumber(struct dentry *dentry)
 65 {
 66         const char *name;
 67         unsigned int s;
 68 
 69         if (dentry->d_name.len != 3)
 70                 return -1;
 71         name = dentry->d_name.name;
 72         if (name[0] < '' || name[0] > '9' ||
 73             name[1] < '' || name[1] > '9' ||
 74             name[2] < '' || name[2] > '9')
 75                 return -1;
 76         s = name[0] - '';
 77         s = s * 10 + name[1] - '';
 78         s = s * 10 + name[2] - '';
 79         return s;
 80 }
 81 
 82 /*
 83  * utility functions; should be called with the kernel lock held
 84  * to protect against busses/devices appearing/disappearing
 85  */
 86 
 87 static void new_dev_inode(struct usb_device *dev, struct super_block *sb)
 88 {
 89         struct inode *inode;
 90         unsigned int devnum = dev->devnum;
 91         unsigned int busnum = dev->bus->busnum;
 92 
 93         if (devnum < 1 || devnum > 127 || busnum > 255)
 94                 return;
 95         inode = iget(sb, IDEVICE | (busnum << 8) | devnum);
 96         if (!inode) {
 97                 printk(KERN_ERR "usbdevfs: cannot create inode for bus %u device %u\n", busnum, devnum);
 98                 return;
 99         }
100         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
101         inode->i_uid = sb->u.usbdevfs_sb.devuid;
102         inode->i_gid = sb->u.usbdevfs_sb.devgid;
103         inode->i_mode = sb->u.usbdevfs_sb.devmode | S_IFREG;
104         inode->i_fop = &usbdevfs_device_file_operations;
105         inode->i_size = sizeof(struct usb_device_descriptor);
106         inode->u.usbdev_i.p.dev = dev;
107         list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
108         list_add_tail(&inode->u.usbdev_i.dlist, &dev->inodes);
109 }
110 
111 static void recurse_new_dev_inode(struct usb_device *dev, struct super_block *sb)
112 {
113         unsigned int i;
114 
115         if (!dev)
116                 return;
117         new_dev_inode(dev, sb);
118         for (i = 0; i < dev->maxchild; i++) {
119                 if (!dev->children[i])
120                         continue;
121                 recurse_new_dev_inode(dev->children[i], sb);
122         }
123 }
124 
125 static void new_bus_inode(struct usb_bus *bus, struct super_block *sb)
126 {
127         struct inode *inode;
128         unsigned int busnum = bus->busnum;
129 
130         if (busnum > 255)
131                 return;
132         inode = iget(sb, IBUS | (busnum << 8));
133         if (!inode) {
134                 printk(KERN_ERR "usbdevfs: cannot create inode for bus %u\n", busnum);
135                 return;
136         }
137         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
138         inode->i_uid = sb->u.usbdevfs_sb.busuid;
139         inode->i_gid = sb->u.usbdevfs_sb.busgid;
140         inode->i_mode = sb->u.usbdevfs_sb.busmode | S_IFDIR;
141         inode->i_op = &usbdevfs_bus_inode_operations;
142         inode->i_fop = &usbdevfs_bus_file_operations;
143         inode->u.usbdev_i.p.bus = bus;
144         list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
145         list_add_tail(&inode->u.usbdev_i.dlist, &bus->inodes);
146 }
147 
148 static void free_inode(struct inode *inode)
149 {
150         inode->u.usbdev_i.p.bus = NULL;
151         inode->u.usbdev_i.p.dev = NULL;
152         inode->i_mode &= ~S_IRWXUGO;
153         inode->i_uid = inode->i_gid = 0;
154         inode->i_size = 0;
155         list_del(&inode->u.usbdev_i.slist);
156         INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
157         list_del(&inode->u.usbdev_i.dlist);
158         INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
159         iput(inode);
160 }
161 
162 static struct usb_bus *usbdevfs_findbus(int busnr)
163 {
164         struct list_head *list;
165         struct usb_bus *bus;
166 
167         for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
168                 bus = list_entry(list, struct usb_bus, bus_list);
169                 if (bus->busnum == busnr)
170                         return bus;
171         }
172         return NULL;
173 }
174 
175 #if 0
176 static struct usb_device *finddev(struct usb_device *dev, int devnr)
177 {
178         unsigned int i;
179         struct usb_device *d2;
180 
181         if (!dev)
182                 return NULL;
183         if (dev->devnum == devnr)
184                 return dev;
185         for (i = 0; i < dev->maxchild; i++) {
186                 if (!dev->children[i])
187                         continue;
188                 if ((d2 = finddev(dev->children[i], devnr)))
189                         return d2;
190         }
191         return NULL;
192 }
193 
194 static struct usb_device *usbdevfs_finddevice(struct usb_bus *bus, int devnr)
195 {
196         return finddev(bus->root_hub, devnr);
197 }
198 #endif
199 
200 /* --------------------------------------------------------------------- */
201 
202 static int usbdevfs_revalidate(struct dentry *dentry, int flags)
203 {
204         struct inode *inode = dentry->d_inode;
205 
206         if (!inode)
207                 return 0;
208         if (ITYPE(inode->i_ino) == IBUS && !inode->u.usbdev_i.p.bus)
209                 return 0;
210         if (ITYPE(inode->i_ino) == IDEVICE && !inode->u.usbdev_i.p.dev)
211                 return 0;
212         return 1;
213 }
214 
215 static struct dentry_operations usbdevfs_dentry_operations = {
216         d_revalidate:   usbdevfs_revalidate,
217 };
218 
219 static struct dentry *usbdevfs_root_lookup(struct inode *dir, struct dentry *dentry)
220 {
221         int busnr;
222         unsigned long ino = 0;
223         unsigned int i;
224         struct inode *inode;
225 
226         /* sanity check */
227         if (dir->i_ino != IROOT)
228                 return ERR_PTR(-EINVAL);
229         dentry->d_op = &usbdevfs_dentry_operations;
230         busnr = dnumber(dentry);
231         if (busnr >= 0 && busnr <= 255)
232                 ino = IBUS | (busnr << 8);
233         if (!ino) {
234                 for (i = 0; i < NRSPECIAL; i++) {
235                         if (strlen(special[i].name) == dentry->d_name.len && 
236                             !strncmp(special[i].name, dentry->d_name.name, dentry->d_name.len)) {
237                                 ino = ISPECIAL | (i + IROOT + 1);
238                                 break;
239                         }
240                 }
241         }
242         if (!ino)
243                 return ERR_PTR(-ENOENT);
244         inode = iget(dir->i_sb, ino);
245         if (!inode)
246                 return ERR_PTR(-EINVAL);
247         if (inode && ITYPE(ino) == IBUS && inode->u.usbdev_i.p.bus == NULL) {
248                 iput(inode);
249                 inode = NULL;
250         }
251         d_add(dentry, inode);
252         return NULL;
253 }
254 
255 static struct dentry *usbdevfs_bus_lookup(struct inode *dir, struct dentry *dentry)
256 {
257         struct inode *inode;
258         int devnr;
259 
260         /* sanity check */
261         if (ITYPE(dir->i_ino) != IBUS)
262                 return ERR_PTR(-EINVAL);
263         dentry->d_op = &usbdevfs_dentry_operations;
264         devnr = dnumber(dentry);
265         if (devnr < 1 || devnr > 127)
266                 return ERR_PTR(-ENOENT);
267         inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
268         if (!inode)
269                 return ERR_PTR(-EINVAL);
270         if (inode && inode->u.usbdev_i.p.dev == NULL) {
271                 iput(inode);
272                 inode = NULL;
273         }
274         d_add(dentry, inode);
275         return NULL;
276 }
277 
278 static int usbdevfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
279 {
280         struct inode *inode = filp->f_dentry->d_inode;
281         unsigned long ino = inode->i_ino;
282         struct special *spec;
283         struct list_head *list;
284         struct usb_bus *bus;
285         char numbuf[8];
286         unsigned int i;
287 
288         /* sanity check */
289         if (ino != IROOT)
290                 return -EINVAL;
291         i = filp->f_pos;
292         switch (i) {
293         case 0:
294                 if (filldir(dirent, ".", 1, i, IROOT, DT_DIR) < 0)
295                         return 0;
296                 filp->f_pos++;
297                 i++;
298                 /* fall through */
299 
300         case 1:
301                 if (filldir(dirent, "..", 2, i, IROOT, DT_DIR) < 0)
302                         return 0;
303                 filp->f_pos++;
304                 i++;
305                 /* fall through */
306 
307         default:
308                 
309                 while (i >= 2 && i < 2+NRSPECIAL) {
310                         spec = &special[filp->f_pos-2];
311                         if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT), DT_UNKNOWN) < 0)
312                                 return 0;
313                         filp->f_pos++;
314                         i++;
315                 }
316                 if (i < 2+NRSPECIAL)
317                         return 0;
318                 i -= 2+NRSPECIAL;
319                 lock_kernel();
320                 for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
321                         if (i > 0) {
322                                 i--;
323                                 continue;
324                         }
325                         bus = list_entry(list, struct usb_bus, bus_list);
326                         sprintf(numbuf, "%03d", bus->busnum);
327                         if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8), DT_UNKNOWN) < 0)
328                                 break;
329                         filp->f_pos++;
330                 }
331                 unlock_kernel();
332                 return 0;
333         }
334 }
335 
336 static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct file *filp, void *dirent, filldir_t filldir)
337 {
338         char numbuf[8];
339         unsigned int i;
340 
341         if (!dev)
342                 return pos;
343         sprintf(numbuf, "%03d", dev->devnum);
344         if (pos > 0)
345                 pos--;
346         else {
347                 if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff), DT_UNKNOWN) < 0)
348                         return -1;
349                 filp->f_pos++;
350         }
351         for (i = 0; i < dev->maxchild; i++) {
352                 if (!dev->children[i])
353                         continue;
354                 pos = bus_readdir(dev->children[i], ino, pos, filp, dirent, filldir);
355                 if (pos < 0)
356                         return -1;
357         }
358         return pos;
359 }
360 
361 static int usbdevfs_bus_readdir(struct file *filp, void *dirent, filldir_t filldir)
362 {
363         struct inode *inode = filp->f_dentry->d_inode;
364         unsigned long ino = inode->i_ino;
365         struct usb_bus *bus;
366 
367         /* sanity check */
368         if (ITYPE(ino) != IBUS)
369                 return -EINVAL;
370         switch ((unsigned int)filp->f_pos) {
371         case 0:
372                 if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) < 0)
373                         return 0;
374                 filp->f_pos++;
375                 /* fall through */
376 
377         case 1:
378                 if (filldir(dirent, "..", 2, filp->f_pos, IROOT, DT_DIR) < 0)
379                         return 0;
380                 filp->f_pos++;
381                 /* fall through */
382 
383         default:
384                 lock_kernel();
385                 bus = usbdevfs_findbus(IBUSNR(ino));
386                 bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8), filp->f_pos-2, filp, dirent, filldir);
387                 unlock_kernel();
388                 return 0;
389         }
390 }
391 
392 static struct file_operations usbdevfs_root_file_operations = {
393         readdir: usbdevfs_root_readdir,
394 };
395 
396 static struct inode_operations usbdevfs_root_inode_operations = {
397         lookup: usbdevfs_root_lookup,
398 };
399 
400 static struct file_operations usbdevfs_bus_file_operations = {
401         readdir: usbdevfs_bus_readdir,
402 };
403 
404 static struct inode_operations usbdevfs_bus_inode_operations = {
405         lookup: usbdevfs_bus_lookup,
406 };
407 
408 static void usbdevfs_read_inode(struct inode *inode)
409 {
410         struct special *spec;
411 
412         inode->i_ctime = inode->i_mtime = inode->i_atime = CURRENT_TIME;
413         inode->i_mode = S_IFREG;
414         inode->i_gid = inode->i_uid = 0;
415         INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
416         INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
417         inode->u.usbdev_i.p.dev = NULL;
418         inode->u.usbdev_i.p.bus = NULL;
419         switch (ITYPE(inode->i_ino)) {
420         case ISPECIAL:
421                 if (inode->i_ino == IROOT) {
422                         inode->i_op = &usbdevfs_root_inode_operations;
423                         inode->i_fop = &usbdevfs_root_file_operations;
424                         inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
425                         return;
426                 }
427                 if (inode->i_ino <= IROOT || inode->i_ino > IROOT+NRSPECIAL)
428                         return;
429                 spec = &special[inode->i_ino-(IROOT+1)];
430                 inode->i_fop = spec->fops;
431                 return;
432 
433         case IDEVICE:
434                 return;
435 
436         case IBUS:
437                 return;
438 
439         default:
440                 return;
441         }
442 }
443 
444 static void usbdevfs_put_super(struct super_block *sb)
445 {
446         list_del(&sb->u.usbdevfs_sb.slist);
447         INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist);
448         while (!list_empty(&sb->u.usbdevfs_sb.ilist))
449                 free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, struct inode, u.usbdev_i.slist));
450 }
451 
452 static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf)
453 {
454         buf->f_type = USBDEVICE_SUPER_MAGIC;
455         buf->f_bsize = PAGE_SIZE/sizeof(long);   /* ??? */
456         buf->f_bfree = 0;
457         buf->f_bavail = 0;
458         buf->f_ffree = 0;
459         buf->f_namelen = NAME_MAX;
460         return 0;
461 }
462 
463 static struct super_operations usbdevfs_sops = { 
464         read_inode:     usbdevfs_read_inode,
465         put_super:      usbdevfs_put_super,
466         statfs:         usbdevfs_statfs,
467 };
468 
469 struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent)
470 {
471         struct inode *root_inode, *inode;
472         struct list_head *blist;
473         struct usb_bus *bus;
474         unsigned int i;
475         uid_t devuid = 0, busuid = 0, listuid = 0;
476         gid_t devgid = 0, busgid = 0, listgid = 0;
477         umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
478         char *curopt = NULL, *value;
479 
480         /* parse options */
481         if (data)
482                 curopt = strtok(data, ",");
483         for (; curopt; curopt = strtok(NULL, ",")) {
484                 if ((value = strchr(curopt, '=')) != NULL)
485                         *value++ = 0;
486                 if (!strcmp(curopt, "devuid")) {
487                         if (!value || !value[0])
488                                 goto opterr;
489                         devuid = simple_strtoul(value, &value, 0);
490                         if (*value)
491                                 goto opterr;
492                 }
493                 if (!strcmp(curopt, "devgid")) {
494                         if (!value || !value[0])
495                                 goto opterr;
496                         devgid = simple_strtoul(value, &value, 0);
497                         if (*value)
498                                 goto opterr;
499                 }
500                 if (!strcmp(curopt, "devmode")) {
501                         if (!value || !value[0])
502                                 goto opterr;
503                         devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
504                         if (*value)
505                                 goto opterr;
506                 }
507                 if (!strcmp(curopt, "busuid")) {
508                         if (!value || !value[0])
509                                 goto opterr;
510                         busuid = simple_strtoul(value, &value, 0);
511                         if (*value)
512                                 goto opterr;
513                 }
514                 if (!strcmp(curopt, "busgid")) {
515                         if (!value || !value[0])
516                                 goto opterr;
517                         busgid = simple_strtoul(value, &value, 0);
518                         if (*value)
519                                 goto opterr;
520                 }
521                 if (!strcmp(curopt, "busmode")) {
522                         if (!value || !value[0])
523                                 goto opterr;
524                         busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
525                         if (*value)
526                                 goto opterr;
527                 }
528                 if (!strcmp(curopt, "listuid")) {
529                         if (!value || !value[0])
530                                 goto opterr;
531                         listuid = simple_strtoul(value, &value, 0);
532                         if (*value)
533                                 goto opterr;
534                 }
535                 if (!strcmp(curopt, "listgid")) {
536                         if (!value || !value[0])
537                                 goto opterr;
538                         listgid = simple_strtoul(value, &value, 0);
539                         if (*value)
540                                 goto opterr;
541                 }
542                 if (!strcmp(curopt, "listmode")) {
543                         if (!value || !value[0])
544                                 goto opterr;
545                         listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
546                         if (*value)
547                                 goto opterr;
548                 }
549         }
550         /* fill superblock */
551         s->s_blocksize = 1024;
552         s->s_blocksize_bits = 10;
553         s->s_magic = USBDEVICE_SUPER_MAGIC;
554         s->s_op = &usbdevfs_sops;
555         INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
556         INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
557         s->u.usbdevfs_sb.devuid = devuid;
558         s->u.usbdevfs_sb.devgid = devgid;
559         s->u.usbdevfs_sb.devmode = devmode;
560         s->u.usbdevfs_sb.busuid = busuid;
561         s->u.usbdevfs_sb.busgid = busgid;
562         s->u.usbdevfs_sb.busmode = busmode;
563         root_inode = iget(s, IROOT);
564         if (!root_inode)
565                 goto out_no_root;
566         s->s_root = d_alloc_root(root_inode);
567         if (!s->s_root)
568                 goto out_no_root;
569         list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
570         for (i = 0; i < NRSPECIAL; i++) {
571                 if (!(inode = iget(s, IROOT+1+i)))
572                         continue;
573                 inode->i_uid = listuid;
574                 inode->i_gid = listgid;
575                 inode->i_mode = listmode | S_IFREG;
576                 special[i].inode = inode;
577                 list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
578                 list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
579         }
580         lock_kernel();
581         for (blist = usb_bus_list.next; blist != &usb_bus_list; blist = blist->next) {
582                 bus = list_entry(blist, struct usb_bus, bus_list);
583                 new_bus_inode(bus, s);
584                 recurse_new_dev_inode(bus->root_hub, s);
585         }
586         unlock_kernel();
587         return s;
588 
589  out_no_root:
590         printk("usbdevfs_read_super: get root inode failed\n");
591         iput(root_inode);
592         return NULL;
593 
594  opterr:
595         printk(KERN_WARNING "usbdevfs: mount parameter error\n");
596         return NULL;
597 }
598 
599 static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, 0);
600 
601 /* --------------------------------------------------------------------- */
602 
603 static void update_special_inodes (void)
604 {
605         int i;
606         for (i = 0; i < NRSPECIAL; i++) {
607                 struct inode *inode = special[i].inode;
608                 if (inode)
609                         inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
610         }
611 }
612 
613 
614 void usbdevfs_add_bus(struct usb_bus *bus)
615 {
616         struct list_head *slist;
617 
618         lock_kernel();
619         for (slist = superlist.next; slist != &superlist; slist = slist->next)
620                 new_bus_inode(bus, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
621         update_special_inodes();
622         unlock_kernel();
623         usbdevfs_conn_disc_event();
624 }
625 
626 void usbdevfs_remove_bus(struct usb_bus *bus)
627 {
628         lock_kernel();
629         while (!list_empty(&bus->inodes))
630                 free_inode(list_entry(bus->inodes.next, struct inode, u.usbdev_i.dlist));
631         update_special_inodes();
632         unlock_kernel();
633         usbdevfs_conn_disc_event();
634 }
635 
636 void usbdevfs_add_device(struct usb_device *dev)
637 {
638         struct list_head *slist;
639 
640         lock_kernel();
641         for (slist = superlist.next; slist != &superlist; slist = slist->next)
642                 new_dev_inode(dev, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
643         update_special_inodes();
644         unlock_kernel();
645         usbdevfs_conn_disc_event();
646 }
647 
648 void usbdevfs_remove_device(struct usb_device *dev)
649 {
650         struct dev_state *ds;
651         struct siginfo sinfo;
652 
653         lock_kernel();
654         while (!list_empty(&dev->inodes))
655                 free_inode(list_entry(dev->inodes.next, struct inode, u.usbdev_i.dlist));
656         while (!list_empty(&dev->filelist)) {
657                 ds = list_entry(dev->filelist.next, struct dev_state, list);
658                 list_del(&ds->list);
659                 INIT_LIST_HEAD(&ds->list);
660                 down_write(&ds->devsem);
661                 ds->dev = NULL;
662                 up_write(&ds->devsem);
663                 if (ds->discsignr) {
664                         sinfo.si_signo = SIGPIPE;
665                         sinfo.si_errno = EPIPE;
666                         sinfo.si_code = SI_ASYNCIO;
667                         sinfo.si_addr = ds->disccontext;
668                         send_sig_info(ds->discsignr, &sinfo, ds->disctask);
669                 }
670         }
671 
672         update_special_inodes();
673         unlock_kernel();
674         usbdevfs_conn_disc_event();
675 }
676 
677 /* --------------------------------------------------------------------- */
678 
679 #ifdef CONFIG_PROC_FS           
680 static struct proc_dir_entry *usbdir = NULL;
681 #endif  
682 
683 int __init usbdevfs_init(void)
684 {
685         int ret;
686 
687         for (ret = 0; ret < NRSPECIAL; ret++) {
688                 INIT_LIST_HEAD(&special[ret].inodes);
689         }
690         if ((ret = usb_register(&usbdevfs_driver)))
691                 return ret;
692         if ((ret = register_filesystem(&usbdevice_fs_type)))
693                 usb_deregister(&usbdevfs_driver);
694 #ifdef CONFIG_PROC_FS           
695         /* create mount point for usbdevfs */
696         usbdir = proc_mkdir("usb", proc_bus);
697 #endif  
698         return ret;
699 }
700 
701 void __exit usbdevfs_cleanup(void)
702 {
703         usb_deregister(&usbdevfs_driver);
704         unregister_filesystem(&usbdevice_fs_type);
705 #ifdef CONFIG_PROC_FS   
706         if (usbdir)
707                 remove_proc_entry("usb", proc_bus);
708 #endif
709 }
710 
711 #if 0
712 module_init(usbdevfs_init);
713 module_exit(usbdevfs_cleanup);
714 #endif
715 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.