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