file.c (50501936288d6a29d7ef78f25d00e33240fad45f) | file.c (015fbddefcfbf8b44c89b2e9b0b3dd77631f1e51) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * drivers/usb/core/file.c 4 * 5 * (C) Copyright Linus Torvalds 1999 6 * (C) Copyright Johannes Erdfelt 1999-2001 7 * (C) Copyright Andreas Gal 1999 8 * (C) Copyright Gregory P. Smith 1999 --- 15 unchanged lines hidden (view full) --- 24#include <linux/string.h> 25#include <linux/usb.h> 26 27#include "usb.h" 28 29#define MAX_USB_MINORS 256 30static const struct file_operations *usb_minors[MAX_USB_MINORS]; 31static DECLARE_RWSEM(minor_rwsem); | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * drivers/usb/core/file.c 4 * 5 * (C) Copyright Linus Torvalds 1999 6 * (C) Copyright Johannes Erdfelt 1999-2001 7 * (C) Copyright Andreas Gal 1999 8 * (C) Copyright Gregory P. Smith 1999 --- 15 unchanged lines hidden (view full) --- 24#include <linux/string.h> 25#include <linux/usb.h> 26 27#include "usb.h" 28 29#define MAX_USB_MINORS 256 30static const struct file_operations *usb_minors[MAX_USB_MINORS]; 31static DECLARE_RWSEM(minor_rwsem); |
32static DEFINE_MUTEX(init_usb_class_mutex); | |
33 34static int usb_open(struct inode *inode, struct file *file) 35{ 36 int err = -ENODEV; 37 const struct file_operations *new_fops; 38 39 down_read(&minor_rwsem); 40 new_fops = fops_get(usb_minors[iminor(inode)]); --- 11 unchanged lines hidden (view full) --- 52} 53 54static const struct file_operations usb_fops = { 55 .owner = THIS_MODULE, 56 .open = usb_open, 57 .llseek = noop_llseek, 58}; 59 | 32 33static int usb_open(struct inode *inode, struct file *file) 34{ 35 int err = -ENODEV; 36 const struct file_operations *new_fops; 37 38 down_read(&minor_rwsem); 39 new_fops = fops_get(usb_minors[iminor(inode)]); --- 11 unchanged lines hidden (view full) --- 51} 52 53static const struct file_operations usb_fops = { 54 .owner = THIS_MODULE, 55 .open = usb_open, 56 .llseek = noop_llseek, 57}; 58 |
60static struct usb_class { 61 struct kref kref; 62 struct class *class; 63} *usb_class; 64 | |
65static char *usb_devnode(const struct device *dev, umode_t *mode) 66{ 67 struct usb_class_driver *drv; 68 69 drv = dev_get_drvdata(dev); 70 if (!drv || !drv->devnode) 71 return NULL; 72 return drv->devnode(dev, mode); 73} 74 | 59static char *usb_devnode(const struct device *dev, umode_t *mode) 60{ 61 struct usb_class_driver *drv; 62 63 drv = dev_get_drvdata(dev); 64 if (!drv || !drv->devnode) 65 return NULL; 66 return drv->devnode(dev, mode); 67} 68 |
75static int init_usb_class(void) 76{ 77 int result = 0; | 69const struct class usbmisc_class = { 70 .name = "usbmisc", 71 .devnode = usb_devnode, 72}; |
78 | 73 |
79 if (usb_class != NULL) { 80 kref_get(&usb_class->kref); 81 goto exit; 82 } 83 84 usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL); 85 if (!usb_class) { 86 result = -ENOMEM; 87 goto exit; 88 } 89 90 kref_init(&usb_class->kref); 91 usb_class->class = class_create("usbmisc"); 92 if (IS_ERR(usb_class->class)) { 93 result = PTR_ERR(usb_class->class); 94 printk(KERN_ERR "class_create failed for usb devices\n"); 95 kfree(usb_class); 96 usb_class = NULL; 97 goto exit; 98 } 99 usb_class->class->devnode = usb_devnode; 100 101exit: 102 return result; 103} 104 105static void release_usb_class(struct kref *kref) 106{ 107 /* Ok, we cheat as we know we only have one usb_class */ 108 class_destroy(usb_class->class); 109 kfree(usb_class); 110 usb_class = NULL; 111} 112 113static void destroy_usb_class(void) 114{ 115 mutex_lock(&init_usb_class_mutex); 116 kref_put(&usb_class->kref, release_usb_class); 117 mutex_unlock(&init_usb_class_mutex); 118} 119 | |
120int usb_major_init(void) 121{ 122 int error; 123 124 error = register_chrdev(USB_MAJOR, "usb", &usb_fops); 125 if (error) 126 printk(KERN_ERR "Unable to get major %d for usb devices\n", 127 USB_MAJOR); --- 23 unchanged lines hidden (view full) --- 151 * the minor numbers given out by this function. 152 * 153 * Return: -EINVAL if something bad happens with trying to register a 154 * device, and 0 on success. 155 */ 156int usb_register_dev(struct usb_interface *intf, 157 struct usb_class_driver *class_driver) 158{ | 74int usb_major_init(void) 75{ 76 int error; 77 78 error = register_chrdev(USB_MAJOR, "usb", &usb_fops); 79 if (error) 80 printk(KERN_ERR "Unable to get major %d for usb devices\n", 81 USB_MAJOR); --- 23 unchanged lines hidden (view full) --- 105 * the minor numbers given out by this function. 106 * 107 * Return: -EINVAL if something bad happens with trying to register a 108 * device, and 0 on success. 109 */ 110int usb_register_dev(struct usb_interface *intf, 111 struct usb_class_driver *class_driver) 112{ |
159 int retval; | 113 int retval = 0; |
160 int minor_base = class_driver->minor_base; 161 int minor; 162 char name[20]; 163 164#ifdef CONFIG_USB_DYNAMIC_MINORS 165 /* 166 * We don't care what the device tries to start at, we want to start 167 * at zero to pack the devices into the smallest available space with 168 * no holes in the minor range. 169 */ 170 minor_base = 0; 171#endif 172 173 if (class_driver->fops == NULL) 174 return -EINVAL; 175 if (intf->minor >= 0) 176 return -EADDRINUSE; 177 | 114 int minor_base = class_driver->minor_base; 115 int minor; 116 char name[20]; 117 118#ifdef CONFIG_USB_DYNAMIC_MINORS 119 /* 120 * We don't care what the device tries to start at, we want to start 121 * at zero to pack the devices into the smallest available space with 122 * no holes in the minor range. 123 */ 124 minor_base = 0; 125#endif 126 127 if (class_driver->fops == NULL) 128 return -EINVAL; 129 if (intf->minor >= 0) 130 return -EADDRINUSE; 131 |
178 mutex_lock(&init_usb_class_mutex); 179 retval = init_usb_class(); 180 mutex_unlock(&init_usb_class_mutex); 181 182 if (retval) 183 return retval; 184 | |
185 dev_dbg(&intf->dev, "looking for a minor, starting at %d\n", minor_base); 186 187 down_write(&minor_rwsem); 188 for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { 189 if (usb_minors[minor]) 190 continue; 191 192 usb_minors[minor] = class_driver->fops; 193 intf->minor = minor; 194 break; 195 } 196 if (intf->minor < 0) { 197 up_write(&minor_rwsem); 198 return -EXFULL; 199 } 200 201 /* create a usb class device for this usb interface */ 202 snprintf(name, sizeof(name), class_driver->name, minor - minor_base); | 132 dev_dbg(&intf->dev, "looking for a minor, starting at %d\n", minor_base); 133 134 down_write(&minor_rwsem); 135 for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { 136 if (usb_minors[minor]) 137 continue; 138 139 usb_minors[minor] = class_driver->fops; 140 intf->minor = minor; 141 break; 142 } 143 if (intf->minor < 0) { 144 up_write(&minor_rwsem); 145 return -EXFULL; 146 } 147 148 /* create a usb class device for this usb interface */ 149 snprintf(name, sizeof(name), class_driver->name, minor - minor_base); |
203 intf->usb_dev = device_create(usb_class->class, &intf->dev, | 150 intf->usb_dev = device_create(&usbmisc_class, &intf->dev, |
204 MKDEV(USB_MAJOR, minor), class_driver, 205 "%s", kbasename(name)); 206 if (IS_ERR(intf->usb_dev)) { 207 usb_minors[minor] = NULL; 208 intf->minor = -1; 209 retval = PTR_ERR(intf->usb_dev); 210 } 211 up_write(&minor_rwsem); --- 17 unchanged lines hidden (view full) --- 229 */ 230void usb_deregister_dev(struct usb_interface *intf, 231 struct usb_class_driver *class_driver) 232{ 233 if (intf->minor == -1) 234 return; 235 236 dev_dbg(&intf->dev, "removing %d minor\n", intf->minor); | 151 MKDEV(USB_MAJOR, minor), class_driver, 152 "%s", kbasename(name)); 153 if (IS_ERR(intf->usb_dev)) { 154 usb_minors[minor] = NULL; 155 intf->minor = -1; 156 retval = PTR_ERR(intf->usb_dev); 157 } 158 up_write(&minor_rwsem); --- 17 unchanged lines hidden (view full) --- 176 */ 177void usb_deregister_dev(struct usb_interface *intf, 178 struct usb_class_driver *class_driver) 179{ 180 if (intf->minor == -1) 181 return; 182 183 dev_dbg(&intf->dev, "removing %d minor\n", intf->minor); |
237 device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); | 184 device_destroy(&usbmisc_class, MKDEV(USB_MAJOR, intf->minor)); |
238 239 down_write(&minor_rwsem); 240 usb_minors[intf->minor] = NULL; 241 up_write(&minor_rwsem); 242 243 intf->usb_dev = NULL; 244 intf->minor = -1; | 185 186 down_write(&minor_rwsem); 187 usb_minors[intf->minor] = NULL; 188 up_write(&minor_rwsem); 189 190 intf->usb_dev = NULL; 191 intf->minor = -1; |
245 destroy_usb_class(); | |
246} 247EXPORT_SYMBOL_GPL(usb_deregister_dev); | 192} 193EXPORT_SYMBOL_GPL(usb_deregister_dev); |