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