linux/drivers/usb/core/file.c
<<
>>
Prefs
   1/*
   2 * drivers/usb/core/file.c
   3 *
   4 * (C) Copyright Linus Torvalds 1999
   5 * (C) Copyright Johannes Erdfelt 1999-2001
   6 * (C) Copyright Andreas Gal 1999
   7 * (C) Copyright Gregory P. Smith 1999
   8 * (C) Copyright Deti Fliegl 1999 (new USB architecture)
   9 * (C) Copyright Randy Dunlap 2000
  10 * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
  11 *      more docs, etc)
  12 * (C) Copyright Yggdrasil Computing, Inc. 2000
  13 *     (usb_device_id matching changes by Adam J. Richter)
  14 * (C) Copyright Greg Kroah-Hartman 2002-2003
  15 *
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/errno.h>
  20#include <linux/rwsem.h>
  21#include <linux/slab.h>
  22#include <linux/string.h>
  23#include <linux/usb.h>
  24
  25#include "usb.h"
  26
  27#define MAX_USB_MINORS  256
  28static const struct file_operations *usb_minors[MAX_USB_MINORS];
  29static DECLARE_RWSEM(minor_rwsem);
  30
  31static int usb_open(struct inode *inode, struct file *file)
  32{
  33        int err = -ENODEV;
  34        const struct file_operations *new_fops;
  35
  36        down_read(&minor_rwsem);
  37        new_fops = fops_get(usb_minors[iminor(inode)]);
  38
  39        if (!new_fops)
  40                goto done;
  41
  42        replace_fops(file, new_fops);
  43        /* Curiouser and curiouser... NULL ->open() as "no device" ? */
  44        if (file->f_op->open)
  45                err = file->f_op->open(inode, file);
  46 done:
  47        up_read(&minor_rwsem);
  48        return err;
  49}
  50
  51static const struct file_operations usb_fops = {
  52        .owner =        THIS_MODULE,
  53        .open =         usb_open,
  54        .llseek =       noop_llseek,
  55};
  56
  57static struct usb_class {
  58        struct kref kref;
  59        struct class *class;
  60} *usb_class;
  61
  62static char *usb_devnode(struct device *dev, umode_t *mode)
  63{
  64        struct usb_class_driver *drv;
  65
  66        drv = dev_get_drvdata(dev);
  67        if (!drv || !drv->devnode)
  68                return NULL;
  69        return drv->devnode(dev, mode);
  70}
  71
  72static int init_usb_class(void)
  73{
  74        int result = 0;
  75
  76        if (usb_class != NULL) {
  77                kref_get(&usb_class->kref);
  78                goto exit;
  79        }
  80
  81        usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL);
  82        if (!usb_class) {
  83                result = -ENOMEM;
  84                goto exit;
  85        }
  86
  87        kref_init(&usb_class->kref);
  88        usb_class->class = class_create(THIS_MODULE, "usbmisc");
  89        if (IS_ERR(usb_class->class)) {
  90                result = PTR_ERR(usb_class->class);
  91                printk(KERN_ERR "class_create failed for usb devices\n");
  92                kfree(usb_class);
  93                usb_class = NULL;
  94                goto exit;
  95        }
  96        usb_class->class->devnode = usb_devnode;
  97
  98exit:
  99        return result;
 100}
 101
 102static void release_usb_class(struct kref *kref)
 103{
 104        /* Ok, we cheat as we know we only have one usb_class */
 105        class_destroy(usb_class->class);
 106        kfree(usb_class);
 107        usb_class = NULL;
 108}
 109
 110static void destroy_usb_class(void)
 111{
 112        if (usb_class)
 113                kref_put(&usb_class->kref, release_usb_class);
 114}
 115
 116int usb_major_init(void)
 117{
 118        int error;
 119
 120        error = register_chrdev(USB_MAJOR, "usb", &usb_fops);
 121        if (error)
 122                printk(KERN_ERR "Unable to get major %d for usb devices\n",
 123                       USB_MAJOR);
 124
 125        return error;
 126}
 127
 128void usb_major_cleanup(void)
 129{
 130        unregister_chrdev(USB_MAJOR, "usb");
 131}
 132
 133/**
 134 * usb_register_dev - register a USB device, and ask for a minor number
 135 * @intf: pointer to the usb_interface that is being registered
 136 * @class_driver: pointer to the usb_class_driver for this device
 137 *
 138 * This should be called by all USB drivers that use the USB major number.
 139 * If CONFIG_USB_DYNAMIC_MINORS is enabled, the minor number will be
 140 * dynamically allocated out of the list of available ones.  If it is not
 141 * enabled, the minor number will be based on the next available free minor,
 142 * starting at the class_driver->minor_base.
 143 *
 144 * This function also creates a usb class device in the sysfs tree.
 145 *
 146 * usb_deregister_dev() must be called when the driver is done with
 147 * the minor numbers given out by this function.
 148 *
 149 * Return: -EINVAL if something bad happens with trying to register a
 150 * device, and 0 on success.
 151 */
 152int usb_register_dev(struct usb_interface *intf,
 153                     struct usb_class_driver *class_driver)
 154{
 155        int retval;
 156        int minor_base = class_driver->minor_base;
 157        int minor;
 158        char name[20];
 159
 160#ifdef CONFIG_USB_DYNAMIC_MINORS
 161        /*
 162         * We don't care what the device tries to start at, we want to start
 163         * at zero to pack the devices into the smallest available space with
 164         * no holes in the minor range.
 165         */
 166        minor_base = 0;
 167#endif
 168
 169        if (class_driver->fops == NULL)
 170                return -EINVAL;
 171        if (intf->minor >= 0)
 172                return -EADDRINUSE;
 173
 174        retval = init_usb_class();
 175        if (retval)
 176                return retval;
 177
 178        dev_dbg(&intf->dev, "looking for a minor, starting at %d\n", minor_base);
 179
 180        down_write(&minor_rwsem);
 181        for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
 182                if (usb_minors[minor])
 183                        continue;
 184
 185                usb_minors[minor] = class_driver->fops;
 186                intf->minor = minor;
 187                break;
 188        }
 189        up_write(&minor_rwsem);
 190        if (intf->minor < 0)
 191                return -EXFULL;
 192
 193        /* create a usb class device for this usb interface */
 194        snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
 195        intf->usb_dev = device_create(usb_class->class, &intf->dev,
 196                                      MKDEV(USB_MAJOR, minor), class_driver,
 197                                      "%s", kbasename(name));
 198        if (IS_ERR(intf->usb_dev)) {
 199                down_write(&minor_rwsem);
 200                usb_minors[minor] = NULL;
 201                intf->minor = -1;
 202                up_write(&minor_rwsem);
 203                retval = PTR_ERR(intf->usb_dev);
 204        }
 205        return retval;
 206}
 207EXPORT_SYMBOL_GPL(usb_register_dev);
 208
 209/**
 210 * usb_deregister_dev - deregister a USB device's dynamic minor.
 211 * @intf: pointer to the usb_interface that is being deregistered
 212 * @class_driver: pointer to the usb_class_driver for this device
 213 *
 214 * Used in conjunction with usb_register_dev().  This function is called
 215 * when the USB driver is finished with the minor numbers gotten from a
 216 * call to usb_register_dev() (usually when the device is disconnected
 217 * from the system.)
 218 *
 219 * This function also removes the usb class device from the sysfs tree.
 220 *
 221 * This should be called by all drivers that use the USB major number.
 222 */
 223void usb_deregister_dev(struct usb_interface *intf,
 224                        struct usb_class_driver *class_driver)
 225{
 226        if (intf->minor == -1)
 227                return;
 228
 229        dev_dbg(&intf->dev, "removing %d minor\n", intf->minor);
 230
 231        down_write(&minor_rwsem);
 232        usb_minors[intf->minor] = NULL;
 233        up_write(&minor_rwsem);
 234
 235        device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
 236        intf->usb_dev = NULL;
 237        intf->minor = -1;
 238        destroy_usb_class();
 239}
 240EXPORT_SYMBOL_GPL(usb_deregister_dev);
 241