// SPDX-License-Identifier: GPL-2.0 /* * linux/drivers/char/misc.c * * Generic misc open routine by Johan Myreen * * Based on code from Linus * * Teemu Rantanen's Microsoft Busmouse support and Derrick Cole's * changes incorporated into 0.97pl4 * by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92) * See busmouse.c for particulars. * * Made things a lot mode modular - easy to compile in just one or two * of the misc drivers, as they are now completely independent. Linus. * * Support for loadable modules. 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk> * * Fixed a failing symbol register to free the device registration * Alan Cox <alan@lxorguk.ukuu.org.uk> 21-Jan-96 * * Dynamic minors and /proc/mice by Alessandro Rubini. 26-Mar-96 * * Renamed to misc and miscdevice to be more accurate. Alan Cox 26-Mar-96 * * Handling of mouse minor numbers for kerneld: * Idea by Jacques Gelinas <jack@solucorp.qc.ca>, * adapted by Bjorn Ekwall <bj0rn@blox.se> * corrected by Alan Cox <alan@lxorguk.ukuu.org.uk> * * Changes for kmod (from kerneld): * Cyrus Durgin <cider@speakeasy.org> * * Added devfs support. Richard Gooch <rgooch@atnf.csiro.au> 10-Jan-1998
*/
staticint misc_open(struct inode *inode, struct file *file)
{ int minor = iminor(inode); struct miscdevice *c = NULL, *iter; int err = -ENODEV; conststruct file_operations *new_fops = NULL;
mutex_lock(&misc_mtx);
list_for_each_entry(iter, &misc_list, list) { if (iter->minor != minor) continue;
c = iter;
new_fops = fops_get(iter->fops); break;
}
/* Only request module for fixed minor code */ if (!new_fops && minor < MISC_DYNAMIC_MINOR) {
mutex_unlock(&misc_mtx);
request_module("char-major-%d-%d", MISC_MAJOR, minor);
mutex_lock(&misc_mtx);
list_for_each_entry(iter, &misc_list, list) { if (iter->minor != minor) continue;
c = iter;
new_fops = fops_get(iter->fops); break;
}
}
if (!new_fops) goto fail;
/* * Place the miscdevice in the file's * private_data so it can be used by the * file operations, including f_op->open below
*/
file->private_data = c;
/** * misc_register - register a miscellaneous device * @misc: device structure * * Register a miscellaneous device with the kernel. If the minor * number is set to %MISC_DYNAMIC_MINOR a minor number is assigned * and placed in the minor field of the structure. For other cases * the minor number requested is used. * * The structure passed is linked into the kernel and may not be * destroyed until it has been unregistered. By default, an open() * syscall to the device sets file->private_data to point to the * structure. Drivers don't need open in fops for this. * * A zero is returned on success and a negative errno code for * failure.
*/
int misc_register(struct miscdevice *misc)
{
dev_t dev; int err = 0; bool is_dynamic = (misc->minor == MISC_DYNAMIC_MINOR);
INIT_LIST_HEAD(&misc->list);
mutex_lock(&misc_mtx);
if (is_dynamic) { int i = misc_minor_alloc(misc->minor);
if (i < 0) {
err = -EBUSY; goto out;
}
misc->minor = i;
} else { struct miscdevice *c; int i;
/* * Add it to the front, so that later devices can "override" * earlier defaults
*/
list_add(&misc->list, &misc_list);
out:
mutex_unlock(&misc_mtx); return err;
}
EXPORT_SYMBOL(misc_register);
/** * misc_deregister - unregister a miscellaneous device * @misc: device to unregister * * Unregister a miscellaneous device that was previously * successfully registered with misc_register().
*/
void misc_deregister(struct miscdevice *misc)
{ if (WARN_ON(list_empty(&misc->list))) return;
fail_printk:
pr_err("unable to get major %d for misc devices\n", MISC_MAJOR);
class_unregister(&misc_class);
fail_remove: if (misc_proc_file)
remove_proc_entry("misc", NULL); return err;
}
subsys_initcall(misc_init);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.