linux-old/drivers/usb/inode.c
<<
>>
Prefs
   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/*
  47 * This list of superblocks is still used,
  48 * but since usbdevfs became FS_SINGLE
  49 * there is only one super_block.
  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 * utility functions; should be called with the kernel lock held
  89 * to protect against busses/devices appearing/disappearing
  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        /* parse options */
 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        /* sanity check */
 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        /* sanity check */
 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        /* sanity check */
 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                /* fall through */
 397
 398        case 1:
 399                if (filldir(dirent, "..", 2, i, IROOT, DT_DIR) < 0)
 400                        return 0;
 401                filp->f_pos++;
 402                i++;
 403                /* fall through */
 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        /* sanity check */
 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                /* fall through */
 474
 475        case 1:
 476                if (filldir(dirent, "..", 2, filp->f_pos, IROOT, DT_DIR) < 0)
 477                        return 0;
 478                filp->f_pos++;
 479                /* fall through */
 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        /* fill superblock */
 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 * The usbdevfs name is now deprecated (as of 2.4.19).
 657 * It will be removed when the 2.7.x development cycle is started.
 658 * You have been warned :)
 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        /* create mount point for usbdevfs */
 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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.