usbmon: tentative implementation for 'bus0' interface
Paolo Abeni <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <[email protected]> |
This patch create the bus0 to the usbmon interface. Bus0 provides events for all attached USB buses to any kind of reader (text, binary). Signed-off-by: Paolo Abeni <[email protected]> --- This is test implementation to collect comments and suggestion on the subject. The patch is against linux 2.6.21-rc1. A dummy mon_bus structure is created at usbmon initialization time. This is not attached to any real USB bus, but real mon readers can attach to it. When any event is received from usbmon, the bus0 readers list is walked and attached readers are invoked. Then the event is processed as usual. There are a couple of things that should be polished: - mon_bus->u_bus can now be null and must be tested every time it's used. - at event reception two spinlock must be hold and released: one for bus0 and one for bus-n. Previously only one lock was needed. diff -uprN linux-2.6.21-rc1-mon/drivers/usb/mon/mon_bin.c linux-2.6.21-rc1-monbus0/drivers/usb/mon/mon_bin.c --- linux-2.6.21-rc1-mon/drivers/usb/mon/mon_bin.c 2007-02-27 09:58:04.000000000 +0100 +++ linux-2.6.21-rc1-monbus0/drivers/usb/mon/mon_bin.c 2007-02-28 09:51:07.000000000 +0100 @@ -441,7 +441,7 @@ static void mon_bin_event(struct mon_rea /* We use the fact that usb_pipein() returns 0x80 */ ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe); ep->devnum = usb_pipedevice(urb->pipe); - ep->busnum = rp->r.m_bus->u_bus->busnum; + ep->busnum = urb->dev->bus->busnum; ep->id = (unsigned long) urb; ep->ts_sec = ts.tv_sec; ep->ts_usec = ts.tv_usec; @@ -501,7 +501,7 @@ static void mon_bin_error(void *data, st /* We use the fact that usb_pipein() returns 0x80 */ ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe); ep->devnum = usb_pipedevice(urb->pipe); - ep->busnum = rp->r.m_bus->u_bus->busnum; + ep->busnum = urb->dev->bus->busnum; ep->id = (unsigned long) urb; ep->status = error; @@ -516,7 +516,6 @@ static void mon_bin_error(void *data, st static int mon_bin_open(struct inode *inode, struct file *file) { struct mon_bus *mbus; - struct usb_bus *ubus; struct mon_reader_bin *rp; size_t size; int rc; @@ -526,7 +525,9 @@ static int mon_bin_open(struct inode *in mutex_unlock(&mon_lock); return -ENODEV; } - if ((ubus = mbus->u_bus) == NULL) { + + /* mbus->u_bus is 0 for busnum == 0 */ + if ((mbus->busnum != 0) && (mbus->u_bus == NULL)) { printk(KERN_ERR TAG ": consistency error on open\n"); mutex_unlock(&mon_lock); return -ENODEV; diff -uprN linux-2.6.21-rc1-mon/drivers/usb/mon/mon_main.c linux-2.6.21-rc1-monbus0/drivers/usb/mon/mon_main.c --- linux-2.6.21-rc1-mon/drivers/usb/mon/mon_main.c 2007-02-27 09:34:05.000000000 +0100 +++ linux-2.6.21-rc1-monbus0/drivers/usb/mon/mon_main.c 2007-02-28 09:19:10.000000000 +0100 @@ -25,6 +25,8 @@ static void mon_bus_init(struct usb_bus DEFINE_MUTEX(mon_lock); +static struct mon_bus *bus0; /* Pseudo bus used to collect events + * from all real USB buses */ static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ /* @@ -38,7 +40,7 @@ void mon_reader_add(struct mon_bus *mbus struct usb_bus *ubus; spin_lock_irqsave(&mbus->lock, flags); - if (mbus->nreaders == 0) { + if ((mbus->nreaders == 0) && mbus->u_bus) { ubus = mbus->u_bus; if (ubus->monitored) { /* @@ -78,18 +80,10 @@ void mon_reader_del(struct mon_bus *mbus kref_put(&mbus->ref, mon_bus_drop); } -/* - */ -static void mon_submit(struct usb_bus *ubus, struct urb *urb) +static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb) { - struct mon_bus *mbus; unsigned long flags; struct list_head *pos; - struct mon_reader *r; - - mbus = ubus->mon_bus; - if (mbus == NULL) - goto out_unlocked; spin_lock_irqsave(&mbus->lock, flags); if (mbus->nreaders == 0) @@ -97,31 +91,32 @@ static void mon_submit(struct usb_bus *u mbus->cnt_events++; list_for_each (pos, &mbus->r_list) { - r = list_entry(pos, struct mon_reader, r_link); + struct mon_reader *r = list_entry(pos, struct mon_reader, r_link); r->rnf_submit(r->r_data, urb); } - spin_unlock_irqrestore(&mbus->lock, flags); - return; - out_locked: spin_unlock_irqrestore(&mbus->lock, flags); -out_unlocked: return; } /* */ -static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) +static void mon_submit(struct usb_bus *ubus, struct urb *urb) { struct mon_bus *mbus; - unsigned long flags; - struct list_head *pos; - struct mon_reader *r; + mon_bus_submit(bus0, urb); mbus = ubus->mon_bus; if (mbus == NULL) - goto out_unlocked; + return; + mon_bus_submit(mbus, urb); +} + +static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int error) +{ + unsigned long flags; + struct list_head *pos; spin_lock_irqsave(&mbus->lock, flags); if (mbus->nreaders == 0) @@ -129,27 +124,49 @@ static void mon_submit_error(struct usb_ mbus->cnt_events++; list_for_each (pos, &mbus->r_list) { - r = list_entry(pos, struct mon_reader, r_link); + struct mon_reader *r = list_entry(pos, struct mon_reader, r_link); r->rnf_error(r->r_data, urb, error); } - spin_unlock_irqrestore(&mbus->lock, flags); - return; - out_locked: spin_unlock_irqrestore(&mbus->lock, flags); -out_unlocked: return; } /* */ -static void mon_complete(struct usb_bus *ubus, struct urb *urb) +static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) { struct mon_bus *mbus; + mon_bus_submit_error(bus0, urb, error); + + mbus = ubus->mon_bus; + if (mbus == NULL) + return; + mon_bus_submit(mbus, urb); +} + +static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb) +{ unsigned long flags; struct list_head *pos; - struct mon_reader *r; + + spin_lock_irqsave(&mbus->lock, flags); + mbus->cnt_events++; + list_for_each (pos, &mbus->r_list) { + struct mon_reader *r = list_entry(pos, struct mon_reader, r_link); + r->rnf_complete(r->r_data, urb); + } + spin_unlock_irqrestore(&mbus->lock, flags); + +} + +/* + */ +static void mon_complete(struct usb_bus *ubus, struct urb *urb) +{ + struct mon_bus *mbus; + mon_bus_complete(bus0, urb); mbus = ubus->mon_bus; if (mbus == NULL) { @@ -162,13 +179,7 @@ static void mon_complete(struct usb_bus return; } - spin_lock_irqsave(&mbus->lock, flags); - mbus->cnt_events++; - list_for_each (pos, &mbus->r_list) { - r = list_entry(pos, struct mon_reader, r_link); - r->rnf_complete(r->r_data, urb); - } - spin_unlock_irqrestore(&mbus->lock, flags); + mon_bus_complete(mbus, urb); } /* int (*unlink_urb) (struct urb *urb, int status); */ @@ -255,14 +266,15 @@ static void mon_dissolve(struct mon_bus /* * Never happens, but... */ - if (ubus->monitored) { + if (ubus && ubus->monitored) { printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n", ubus->busnum); ubus->monitored = 0; mb(); } - ubus->mon_bus = NULL; + if (ubus) + ubus->mon_bus = NULL; mbus->u_bus = NULL; mb(); } @@ -296,11 +308,18 @@ static void mon_bus_init(struct usb_bus * a notification if the bus is about to be removed. */ mbus->u_bus = ubus; - ubus->mon_bus = mbus; + if (ubus) { + ubus->mon_bus = mbus; + mbus->busnum = ubus->busnum; + } + else { + bus0 = mbus; + mbus->busnum = 0; + } mbus->uses_dma = ubus->uses_dma; - mbus->text_inited = mon_text_add(mbus, ubus); - mbus->bin_inited = mon_bin_add(mbus, ubus); + mbus->text_inited = mon_text_add(mbus); + mbus->bin_inited = mon_bin_add(mbus); mutex_lock(&mon_lock); list_add_tail(&mbus->bus_link, &mon_buses); @@ -338,6 +357,8 @@ static int __init mon_init(void) struct usb_bus *ubus; int rc; + /* add 'bus 0' */ + mon_bus_init(0); if ((rc = mon_text_init()) != 0) goto err_text; if ((rc = mon_bin_init()) != 0) diff -uprN linux-2.6.21-rc1-mon/drivers/usb/mon/usb_mon.h linux-2.6.21-rc1-monbus0/drivers/usb/mon/usb_mon.h --- linux-2.6.21-rc1-mon/drivers/usb/mon/usb_mon.h 2007-02-27 09:34:05.000000000 +0100 +++ linux-2.6.21-rc1-monbus0/drivers/usb/mon/usb_mon.h 2007-02-28 09:28:36.000000000 +0100 @@ -18,6 +18,7 @@ struct mon_bus { struct list_head bus_link; spinlock_t lock; struct usb_bus *u_bus; + int busnum; int text_inited; int bin_inited; -- Email.it, the professional e-mail, gratis per te: http://www.email.it/f Sponsor: Video Corsi GRATIS - Scopri come imparare velocemente e senza stress (Internet, Informatica, Web Marketing, Hobby Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=5145&d=28-2 ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ [email protected] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel