// SPDX-License-Identifier: GPL-2.0 /* * The USB Monitor, inspired by Dave Harding's USBMon. * * mon_main.c: Main file, module initiation and exit, registrations, etc. * * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
*/
struct mon_bus mon_bus0; /* Pseudo bus meaning "all buses" */ static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */
/* * Link a reader into the bus. * * This must be called with mon_lock taken because of mbus->ref.
*/ void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
{ unsignedlong flags; struct list_head *p;
/* * Unlink reader from the bus. * * This is called with mon_lock taken, so we can decrement mbus->ref.
*/ void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
{ unsignedlong flags;
if (mbus == &mon_bus0) {
list_for_each_entry(mbus, &mon_buses, bus_link) { /* * We do not change nreaders here, so rely on mon_lock.
*/ if (mbus->nreaders == 0 && (ubus = mbus->u_bus) != NULL)
ubus->monitored = 0;
}
} else { /* * A stop can be called for a dissolved mon_bus in case of * a reader staying across an rmmod foo_hcd, so test ->u_bus.
*/ if (mon_bus0.nreaders == 0 && (ubus = mbus->u_bus) != NULL) {
ubus->monitored = 0;
mb();
}
}
}
/* * Add a USB bus (usually by a modprobe foo-hcd) * * This does not return an error code because the core cannot care less * if monitoring is not established.
*/ staticvoid mon_bus_add(struct usb_bus *ubus)
{
mon_bus_init(ubus);
mutex_lock(&mon_lock); if (mon_bus0.nreaders != 0)
ubus->monitored = 1;
mutex_unlock(&mon_lock);
}
/* * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
*/ staticvoid mon_bus_remove(struct usb_bus *ubus)
{ struct mon_bus *mbus = ubus->mon_bus;
mutex_lock(&mon_lock);
list_del(&mbus->bus_link); if (mbus->text_inited)
mon_text_del(mbus); if (mbus->bin_inited)
mon_bin_del(mbus);
/* * Initialize a bus for us: * - allocate mon_bus * - refcount USB bus struct * - link
*/ staticvoid mon_bus_init(struct usb_bus *ubus)
{ struct mon_bus *mbus;
/* * We don't need to take a reference to ubus, because we receive * a notification if the bus is about to be removed.
*/
mbus->u_bus = ubus;
ubus->mon_bus = mbus;
/* * Search a USB bus by number. Notice that USB bus numbers start from one, * which we may later use to identify "all" with zero. * * This function must be called with mon_lock held. * * This is obviously inefficient and may be revised in the future.
*/ struct mon_bus *mon_bus_lookup(unsignedint num)
{ struct mon_bus *mbus;
staticint __init mon_init(void)
{ struct usb_bus *ubus; int rc, id;
if ((rc = mon_text_init()) != 0) goto err_text; if ((rc = mon_bin_init()) != 0) goto err_bin;
mon_bus0_init();
if (usb_mon_register(&mon_ops_0) != 0) {
printk(KERN_NOTICE TAG ": unable to register with the core\n");
rc = -ENODEV; goto err_reg;
} // MOD_INC_USE_COUNT(which_module?);
while (!list_empty(&mon_buses)) {
p = mon_buses.next;
mbus = list_entry(p, struct mon_bus, bus_link);
list_del(p);
if (mbus->text_inited)
mon_text_del(mbus); if (mbus->bin_inited)
mon_bin_del(mbus);
/* * This never happens, because the open/close paths in * file level maintain module use counters and so rmmod fails * before reaching here. However, better be safe...
*/ if (mbus->nreaders) {
printk(KERN_ERR TAG ": Outstanding opens (%d) on usb%d, leaking...\n",
mbus->nreaders, mbus->u_bus->busnum);
kref_get(&mbus->ref); /* Force leak */
}
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.