On Tue, 27 Mar 2007 08:54:32 +0200, Paolo Abeni <[EMAIL PROTECTED]> wrote:

> I was wondering about making available the text extended information
> through the binary interface, without breaking current API. Some
> helper/dummy events could be generated for each isochronous transfer URB
> with number_of_packets > 0, one for each packet used by the transfer.
> This events have event type 'P' (isochronous packet) and id, xfer_type,
> epnum, devnum, busnum equal to the 'main' event field. 

Hmm... Probably not a bad idea as far as ISO descriptors are concerned.
I'll have to think about it. My current patch (see below) puts them
into data, but I see how your idea may be better. I do not like to spread
the event between several messages, but maybe I'm not thinking rationally
about it.

> Ok this is a bit complex :-). Anyway please let me know any suggestion.

No suggestion for now. I would probably go with a single 'P' record
holding all descriptors in its data area.

But there's another side to it, the interval.
It is used in interrupt transfers, without ISO descriptors.
So, I wanted to expand the main record from 48 to 64 bytes.
This is compatible with mmap, but the interface has to be made
"modal": its mode is set with an ioctl. In general, a modal API
is not a good design, so I'm loth to submit it to Greg. The main
sticking point is read(2). One option is to outlaw read(2) access
and leave it for compatible 48 byte accesses only, and provide
a new ioctl to fetch extended headers.

-- Pete

diff -urp -X dontdiff linux-2.6/drivers/usb/mon/mon_bin.c 
linux-2.6.21-mon/drivers/usb/mon/mon_bin.c
--- linux-2.6/drivers/usb/mon/mon_bin.c 2007-03-01 16:17:48.000000000 -0800
+++ linux-2.6.21-mon/drivers/usb/mon/mon_bin.c  2007-03-05 14:59:45.000000000 
-0800
@@ -4,7 +4,7 @@
  * This is a binary format reader.
  *
  * Copyright (C) 2006 Paolo Abeni ([EMAIL PROTECTED])
- * Copyright (C) 2006 Pete Zaitcev ([EMAIL PROTECTED])
+ * Copyright (C) 2006,2007 Pete Zaitcev ([EMAIL PROTECTED])
  */
 
 #include <linux/kernel.h>
@@ -36,6 +36,7 @@
 #define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
 #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
 #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
+#define MON_IOCT_SETAPI _IO(MON_IOC_MAGIC, 9)
 #ifdef CONFIG_COMPAT
 #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32)
 #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32)
@@ -90,7 +91,29 @@ struct mon_bin_hdr {
        int status;
        unsigned int len_urb;   /* Length of data (submitted or actual) */
        unsigned int len_cap;   /* Delivered length */
-       unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
+       union {
+               unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
+               struct iso_rec {
+                       int error_count;
+                       int numdesc;
+               } iso;
+       } s;
+       int interval;
+       int start_frame;
+       unsigned int xfer_flags;
+       unsigned int ndesc;     /* Actual number of ISO descriptors */
+};
+
+/*
+ * ISO vector, packed into the head of data stream.
+ * This has to take 16 bytes to make sure that the end of buffer
+ * wrap is not happening in the middle of a descriptor.
+ */
+struct mon_bin_isodesc {
+       int          iso_status;
+       unsigned int iso_off;
+       unsigned int iso_len;
+       u32 _pad;
 };
 
 /* per file statistic */
@@ -129,6 +152,11 @@ struct mon_bin_mfetch32 {
 #define PKT_ALIGN   64
 #define PKT_SIZE    64
 
+#define PKT_SZ_API0 48 /* API 0 (2.6.20) size */
+#define PKT_SZ_API1 64 /* API 1 size: extra fields */
+
+#define ISODESC_MAX   128      /* Same number as usbfs allows, 2048 bytes. */
+
 /* max number of USB bus supported */
 #define MON_BIN_MAX_MINOR 128
 
@@ -155,6 +183,7 @@ struct mon_reader_bin {
 
        struct mutex fetch_lock;        /* Protect b_read, b_out */
        int mmap_active;
+       int curr_api;
 
        /* A list of these is needed for "bus 0". Some time later. */
        struct mon_reader r;
@@ -172,6 +201,7 @@ static inline struct mon_bin_hdr *MON_OF
 
 #define MON_RING_EMPTY(rp)     ((rp)->b_cnt == 0)
 
+static struct class *mon_bin_class;
 static dev_t mon_bin_dev0;
 static struct cdev mon_bin_cdev;
 
@@ -353,11 +383,10 @@ static inline char mon_bin_get_setup(uns
     const struct urb *urb, char ev_type)
 {
 
-       if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
-               return '-';
-
-       if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+       if (urb->dev->bus->uses_dma &&
+           (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
                return mon_dmapeek(setupb, urb->setup_dma, SETUP_LEN);
+       }
        if (urb->setup_packet == NULL)
                return 'Z';
 
@@ -369,7 +398,8 @@ static char mon_bin_get_data(const struc
     unsigned int offset, struct urb *urb, unsigned int length)
 {
 
-       if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) {
+       if (urb->dev->bus->uses_dma &&
+           (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
                mon_dmapeek_vec(rp, offset, urb->transfer_dma, length);
                return 0;
        }
@@ -381,6 +411,26 @@ static char mon_bin_get_data(const struc
        return 0;
 }
 
+static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
+    unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
+{
+       struct mon_bin_isodesc *dp;
+       struct usb_iso_packet_descriptor *fp;
+
+       fp = urb->iso_frame_desc;
+       while (ndesc-- != 0) {
+               dp = (struct mon_bin_isodesc *)
+                   (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
+               dp->iso_status = fp->status;
+               dp->iso_off = fp->offset;
+               dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length;
+               dp->_pad = 0;
+               if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size)
+                       offset = 0;
+               fp++;
+       }
+}
+
 static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
     char ev_type)
 {
@@ -389,6 +439,7 @@ static void mon_bin_event(struct mon_rea
        unsigned int urb_length;
        unsigned int offset;
        unsigned int length;
+       unsigned int ndesc, lendesc;
        struct mon_bin_hdr *ep;
        char data_tag = 0;
 
@@ -399,6 +450,19 @@ static void mon_bin_event(struct mon_rea
        /*
         * Find the maximum allowable length, then allocate space.
         */
+       if (usb_pipeisoc(urb->pipe)) {
+               if (urb->number_of_packets < 0) {
+                       ndesc = 0;
+               } else if (urb->number_of_packets >= ISODESC_MAX) {
+                       ndesc = ISODESC_MAX;
+               } else {
+                       ndesc = urb->number_of_packets;
+               }
+       } else {
+               ndesc = 0;
+       }
+       lendesc = ndesc*sizeof(struct mon_bin_isodesc);
+
        urb_length = (ev_type == 'S') ?
            urb->transfer_buffer_length : urb->actual_length;
        length = urb_length;
@@ -418,10 +482,12 @@ static void mon_bin_event(struct mon_rea
                }
        }
 
-       if (rp->mmap_active)
-               offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE);
-       else
-               offset = mon_buff_area_alloc(rp, length + PKT_SIZE);
+       if (rp->mmap_active) {
+               offset = mon_buff_area_alloc_contiguous(rp,
+                                                length + PKT_SIZE + lendesc);
+       } else {
+               offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
+       }
        if (offset == ~0) {
                rp->cnt_lost++;
                spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -440,15 +506,37 @@ 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;
        ep->status = urb->status;
        ep->len_urb = urb_length;
-       ep->len_cap = length;
+       ep->len_cap = length + lendesc;
+       ep->xfer_flags = urb->transfer_flags;
+
+       if (usb_pipeint(urb->pipe)) {
+               ep->interval = urb->interval;
+       } else if (usb_pipeisoc(urb->pipe)) {
+               ep->interval = urb->interval;
+               ep->start_frame = urb->start_frame;
+               ep->s.iso.error_count = urb->error_count;
+               ep->s.iso.numdesc = urb->number_of_packets;
+       }
+
+       if (usb_pipecontrol(urb->pipe) && ev_type == 'S') {
+               ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type);
+       } else {
+               ep->flag_setup = '-';
+       }
+
+       if (ndesc != 0) {
+               ep->ndesc = ndesc;
+               mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc);
+               if ((offset += lendesc) >= rp->b_size)
+                       offset -= rp->b_size;
+       }
 
-       ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
        if (length != 0) {
                ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
                if (ep->flag_data != 0) {       /* Yes, it's 0x00, not '0' */
@@ -500,7 +588,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;
 
@@ -515,7 +603,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;
@@ -525,7 +612,7 @@ static int mon_bin_open(struct inode *in
                mutex_unlock(&mon_lock);
                return -ENODEV;
        }
-       if ((ubus = mbus->u_bus) == NULL) {
+       if (mbus != &mon_bus0 && mbus->u_bus == NULL) {
                printk(KERN_ERR TAG ": consistency error on open\n");
                mutex_unlock(&mon_lock);
                return -ENODEV;
@@ -539,7 +626,7 @@ static int mon_bin_open(struct inode *in
        spin_lock_init(&rp->b_lock);
        init_waitqueue_head(&rp->b_wait);
        mutex_init(&rp->fetch_lock);
-
+       rp->curr_api = 0;
        rp->b_size = BUFF_DFL;
 
        size = sizeof(struct mon_pgmap) * (rp->b_size/CHUNK_SIZE);
@@ -581,6 +668,7 @@ static int mon_bin_get_event(struct file
     struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes)
 {
        unsigned long flags;
+       unsigned int hdrbytes;
        struct mon_bin_hdr *ep;
        size_t step_len;
        unsigned int offset;
@@ -588,6 +676,8 @@ static int mon_bin_get_event(struct file
 
        mutex_lock(&rp->fetch_lock);
 
+       hdrbytes = (rp->curr_api)? PKT_SZ_API1: PKT_SZ_API0;
+
        if ((rc = mon_bin_wait_event(file, rp)) < 0) {
                mutex_unlock(&rp->fetch_lock);
                return rc;
@@ -595,7 +685,7 @@ static int mon_bin_get_event(struct file
 
        ep = MON_OFF2HDR(rp, rp->b_out);
 
-       if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) {
+       if (copy_to_user(hdr, ep, hdrbytes)) {
                mutex_unlock(&rp->fetch_lock);
                return -EFAULT;
        }
@@ -643,6 +733,7 @@ static ssize_t mon_bin_read(struct file 
     size_t nbytes, loff_t *ppos)
 {
        struct mon_reader_bin *rp = file->private_data;
+       unsigned int hdrbytes;
        unsigned long flags;
        struct mon_bin_hdr *ep;
        unsigned int offset;
@@ -653,6 +744,8 @@ static ssize_t mon_bin_read(struct file 
 
        mutex_lock(&rp->fetch_lock);
 
+       hdrbytes = (rp->curr_api)? PKT_SZ_API1: PKT_SZ_API0;
+
        if ((rc = mon_bin_wait_event(file, rp)) < 0) {
                mutex_unlock(&rp->fetch_lock);
                return rc;
@@ -660,8 +753,8 @@ static ssize_t mon_bin_read(struct file 
 
        ep = MON_OFF2HDR(rp, rp->b_out);
 
-       if (rp->b_read < sizeof(struct mon_bin_hdr)) {
-               step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read);
+       if (rp->b_read < hdrbytes) {
+               step_len = min(nbytes, hdrbytes - rp->b_read);
                ptr = ((char *)ep) + rp->b_read;
                if (step_len && copy_to_user(buf, ptr, step_len)) {
                        mutex_unlock(&rp->fetch_lock);
@@ -673,10 +766,10 @@ static ssize_t mon_bin_read(struct file 
                done += step_len;
        }
 
-       if (rp->b_read >= sizeof(struct mon_bin_hdr)) {
+       if (rp->b_read >= hdrbytes) {
                step_len = min(nbytes, (size_t)ep->len_cap);
                offset = rp->b_out + PKT_SIZE;
-               offset += rp->b_read - sizeof(struct mon_bin_hdr);
+               offset += rp->b_read - hdrbytes;
                if (offset >= rp->b_size)
                        offset -= rp->b_size;
                if (copy_from_buf(rp, offset, buf, step_len)) {
@@ -692,7 +785,7 @@ static ssize_t mon_bin_read(struct file 
        /*
         * Check if whole packet was read, and if so, jump to the next one.
         */
-       if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) {
+       if (rp->b_read >= hdrbytes + ep->len_cap) {
                spin_lock_irqsave(&rp->b_lock, flags);
                mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
                spin_unlock_irqrestore(&rp->b_lock, flags);
@@ -995,6 +1088,16 @@ static int mon_bin_ioctl(struct inode *i
                }
                break;
 
+       case MON_IOCT_SETAPI:
+               mutex_lock(&rp->fetch_lock);
+               if (arg == 0 || arg == 1) {
+                       rp->curr_api = arg;
+               } else {
+                       ret = -EINVAL;
+               }
+               mutex_unlock(&rp->fetch_lock);
+               break;
+
        default:
                return -ENOTTY;
        }
@@ -1142,10 +1245,38 @@ static void mon_free_buff(struct mon_pgm
                free_page((unsigned long) map[n].ptr);
 }
 
+int mon_bin_add(struct mon_bus *mbus, int busnum)
+{
+       struct device *dev;
+       unsigned minor = busnum;
+
+       if (minor >= MON_BIN_MAX_MINOR)
+               return 0;
+
+       dev = device_create(mon_bin_class, NULL,
+                       MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+       if (IS_ERR(dev))
+               return 0;
+
+       mbus->classdev = dev;
+       return 1;
+}
+
+void mon_bin_del(struct mon_bus *mbus)
+{
+       device_destroy(mon_bin_class, mbus->classdev->devt);
+}
+
 int __init mon_bin_init(void)
 {
        int rc;
 
+       mon_bin_class = class_create(THIS_MODULE, "usbmon");
+       if (IS_ERR(mon_bin_class)) {
+               rc = PTR_ERR(mon_bin_class);
+               goto err_class;
+       }
+
        rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
        if (rc < 0)
                goto err_dev;
@@ -1162,6 +1293,8 @@ int __init mon_bin_init(void)
 err_add:
        unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
 err_dev:
+       class_destroy(mon_bin_class);
+err_class:
        return rc;
 }
 
@@ -1169,4 +1302,5 @@ void mon_bin_exit(void)
 {
        cdev_del(&mon_bin_cdev);
        unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
+       class_destroy(mon_bin_class);
 }
diff -urp -X dontdiff linux-2.6/drivers/usb/mon/mon_main.c 
linux-2.6.21-mon/drivers/usb/mon/mon_main.c
--- linux-2.6/drivers/usb/mon/mon_main.c        2007-02-11 12:39:12.000000000 
-0800
+++ linux-2.6.21-mon/drivers/usb/mon/mon_main.c 2007-03-05 13:14:18.000000000 
-0800
@@ -16,8 +16,6 @@
 #include "usb_mon.h"
 #include "../core/hcd.h"
 
-static void mon_submit(struct usb_bus *ubus, struct urb *urb);
-static void mon_complete(struct usb_bus *ubus, struct urb *urb);
 static void mon_stop(struct mon_bus *mbus);
 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
 static void mon_bus_drop(struct kref *r);
@@ -25,6 +23,7 @@ static void mon_bus_init(struct usb_bus 
 
 DEFINE_MUTEX(mon_lock);
 
+struct mon_bus mon_bus0;               /* Pseudo bus meaning "all buses" */
 static LIST_HEAD(mon_buses);           /* All buses we know: struct mon_bus */
 
 /*
@@ -35,22 +34,19 @@ static LIST_HEAD(mon_buses);                /* All bus
 void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
 {
        unsigned long flags;
-       struct usb_bus *ubus;
+       struct list_head *p;
 
        spin_lock_irqsave(&mbus->lock, flags);
        if (mbus->nreaders == 0) {
-               ubus = mbus->u_bus;
-               if (ubus->monitored) {
-                       /*
-                        * Something is really broken, refuse to go on and
-                        * possibly corrupt ops pointers or worse.
-                        */
-                       printk(KERN_ERR TAG ": bus %d is already monitored\n",
-                           ubus->busnum);
-                       spin_unlock_irqrestore(&mbus->lock, flags);
-                       return;
+               if (mbus == &mon_bus0) {
+                       list_for_each (p, &mon_buses) {
+                               struct mon_bus *m1;
+                               m1 = list_entry(p, struct mon_bus, bus_link);
+                               m1->u_bus->monitored = 1;
+                       }
+               } else {
+                       mbus->u_bus->monitored = 1;
                }
-               ubus->monitored = 1;
        }
        mbus->nreaders++;
        list_add_tail(&r->r_link, &mbus->r_list);
@@ -80,77 +76,79 @@ void mon_reader_del(struct mon_bus *mbus
 
 /*
  */
-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)
-               goto out_locked;
-
        mbus->cnt_events++;
        list_for_each (pos, &mbus->r_list) {
                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(struct usb_bus *ubus, struct urb *urb)
+{
+       struct mon_bus *mbus;
+
+       if ((mbus = ubus->mon_bus) != NULL)
+               mon_bus_submit(mbus, urb);
+       mon_bus_submit(&mon_bus0, urb);
 }
 
 /*
  */
-static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int 
error)
 {
-       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)
-               goto out_locked;
-
        mbus->cnt_events++;
        list_for_each (pos, &mbus->r_list) {
                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_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+{
+       struct mon_bus *mbus;
+
+       if ((mbus = ubus->mon_bus) != NULL)
+               mon_bus_submit_error(mbus, urb, error);
+       mon_bus_submit_error(&mon_bus0, urb, error);
 }
 
 /*
  */
-static void mon_complete(struct usb_bus *ubus, struct urb *urb)
+static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb)
 {
-       struct mon_bus *mbus;
        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) {
+               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;
+
        mbus = ubus->mon_bus;
        if (mbus == NULL) {
                /*
@@ -162,13 +160,8 @@ 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);
+       mon_bus_complete(&mon_bus0, urb);
 }
 
 /* int (*unlink_urb) (struct urb *urb, int status); */
@@ -179,14 +172,26 @@ static void mon_complete(struct usb_bus 
 static void mon_stop(struct mon_bus *mbus)
 {
        struct usb_bus *ubus = mbus->u_bus;
+       struct list_head *p;
 
-       /*
-        * A stop can be called for a dissolved mon_bus in case of
-        * a reader staying across an rmmod foo_hcd.
-        */
-       if (ubus != NULL) {
-               ubus->monitored = 0;
-               mb();
+       if (mbus == &mon_bus0) {
+               list_for_each (p, &mon_buses) {
+                       mbus = list_entry(p, struct mon_bus, 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();
+               }
        }
 }
 
@@ -199,6 +204,10 @@ static void mon_stop(struct mon_bus *mbu
 static void 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);
 }
 
 /*
@@ -212,6 +221,8 @@ static void mon_bus_remove(struct usb_bu
        list_del(&mbus->bus_link);
        if (mbus->text_inited)
                mon_text_del(mbus);
+       if (mbus->bin_inited)
+               mon_bin_del(mbus);
 
        mon_dissolve(mbus, ubus);
        kref_put(&mbus->ref, mon_bus_drop);
@@ -250,12 +261,7 @@ static struct usb_mon_operations mon_ops
 static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
 {
 
-       /*
-        * Never happens, but...
-        */
        if (ubus->monitored) {
-               printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n",
-                   ubus->busnum);
                ubus->monitored = 0;
                mb();
        }
@@ -263,6 +269,8 @@ static void mon_dissolve(struct mon_bus 
        ubus->mon_bus = NULL;
        mbus->u_bus = NULL;
        mb();
+
+       /* We want synchronize_irq() here, but that needs an argument. */
 }
 
 /*
@@ -295,10 +303,9 @@ static void mon_bus_init(struct usb_bus 
         */
        mbus->u_bus = ubus;
        ubus->mon_bus = mbus;
-       mbus->uses_dma = ubus->uses_dma;
 
-       mbus->text_inited = mon_text_add(mbus, ubus);
-       // mon_bin_add(...)
+       mbus->text_inited = mon_text_add(mbus, ubus->busnum);
+       mbus->bin_inited = mon_bin_add(mbus, ubus->busnum);
 
        mutex_lock(&mon_lock);
        list_add_tail(&mbus->bus_link, &mon_buses);
@@ -309,6 +316,18 @@ err_alloc:
        return;
 }
 
+static void mon_bus0_init(void)
+{
+       struct mon_bus *mbus = &mon_bus0;
+
+       kref_init(&mbus->ref);
+       spin_lock_init(&mbus->lock);
+       INIT_LIST_HEAD(&mbus->r_list);
+
+       mbus->text_inited = mon_text_add(mbus, 0);
+       mbus->bin_inited = mon_bin_add(mbus, 0);
+}
+
 /*
  * Search a USB bus by number. Notice that USB bus numbers start from one,
  * which we may later use to identify "all" with zero.
@@ -322,6 +341,9 @@ struct mon_bus *mon_bus_lookup(unsigned 
        struct list_head *p;
        struct mon_bus *mbus;
 
+       if (num == 0) {
+               return &mon_bus0;
+       }
        list_for_each (p, &mon_buses) {
                mbus = list_entry(p, struct mon_bus, bus_link);
                if (mbus->u_bus->busnum == num) {
@@ -341,6 +363,8 @@ static int __init mon_init(void)
        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;
@@ -374,6 +398,7 @@ static void __exit mon_exit(void)
        usb_mon_deregister();
 
        mutex_lock(&mon_lock);
+
        while (!list_empty(&mon_buses)) {
                p = mon_buses.next;
                mbus = list_entry(p, struct mon_bus, bus_link);
@@ -381,6 +406,8 @@ static void __exit mon_exit(void)
 
                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
@@ -397,6 +424,13 @@ static void __exit mon_exit(void)
                mon_dissolve(mbus, mbus->u_bus);
                kref_put(&mbus->ref, mon_bus_drop);
        }
+
+       mbus = &mon_bus0;
+       if (mbus->text_inited)
+               mon_text_del(mbus);
+       if (mbus->bin_inited)
+               mon_bin_del(mbus);
+
        mutex_unlock(&mon_lock);
 
        mon_text_exit();
diff -urp -X dontdiff linux-2.6/drivers/usb/mon/mon_text.c 
linux-2.6.21-mon/drivers/usb/mon/mon_text.c
--- linux-2.6/drivers/usb/mon/mon_text.c        2007-03-01 16:17:48.000000000 
-0800
+++ linux-2.6.21-mon/drivers/usb/mon/mon_text.c 2007-03-05 14:18:00.000000000 
-0800
@@ -31,9 +31,21 @@
  * to a local DoS. But we have to keep to root in order to prevent
  * password sniffing from HID devices.
  */
-#define EVENT_MAX  (2*PAGE_SIZE / sizeof(struct mon_event_text))
+#define EVENT_MAX  (4*PAGE_SIZE / sizeof(struct mon_event_text))
 
-#define PRINTF_DFL  160
+/*
+ * Potentially unlimited number; we limit it for similar allocations.
+ * The usbfs limits this to 128, but we're not quite as generous.
+ */
+#define ISODESC_MAX   5
+
+#define PRINTF_DFL  250   /* with 5 ISOs segs */
+
+struct mon_iso_desc {
+       int status;
+       unsigned int offset;
+       unsigned int length;    /* Unsigned here, signed in URB. Historic. */
+};
 
 struct mon_event_text {
        struct list_head e_link;
@@ -41,10 +53,16 @@ struct mon_event_text {
        unsigned int pipe;      /* Pipe */
        unsigned long id;       /* From pointer, most of the time */
        unsigned int tstamp;
+       int busnum;
        int length;             /* Depends on type: xfer length or act length */
        int status;
+       int interval;
+       int start_frame;
+       int error_count;
        char setup_flag;
        char data_flag;
+       int numdesc;            /* Full number */
+       struct mon_iso_desc isodesc[ISODESC_MAX];
        unsigned char setup[SETUP_MAX];
        unsigned char data[DATA_MAX];
 };
@@ -68,6 +86,28 @@ static struct dentry *mon_dir;               /* Usual
 
 static void mon_text_ctor(void *, struct kmem_cache *, unsigned long);
 
+struct mon_text_ptr {
+       int cnt, limit;
+       char *pbuf;
+};
+
+static struct mon_event_text *
+    mon_text_read_wait(struct mon_reader_text *rp, struct file *file);
+static void mon_text_read_head_t(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_head_u(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_statset(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_intstat(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_isostat(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_isodesc(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep);
+static void mon_text_read_data(struct mon_reader_text *rp,
+    struct mon_text_ptr *p, const struct mon_event_text *ep);
+
 /*
  * mon_text_submit
  * mon_text_complete
@@ -84,8 +124,10 @@ static inline char mon_text_get_setup(st
        if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
                return '-';
 
-       if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+       if (urb->dev->bus->uses_dma &&
+           (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
                return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
+       }
        if (urb->setup_packet == NULL)
                return 'Z';     /* '0' would be not as pretty. */
 
@@ -104,10 +146,10 @@ static inline char mon_text_get_data(str
                len = DATA_MAX;
 
        if (usb_pipein(pipe)) {
-               if (ev_type == 'S')
+               if (ev_type != 'C')
                        return '<';
        } else {
-               if (ev_type == 'C')
+               if (ev_type != 'S')
                        return '>';
        }
 
@@ -120,8 +162,10 @@ static inline char mon_text_get_data(str
         * contain non-NULL garbage in case the upper level promised to
         * set DMA for the HCD.
         */
-       if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+       if (urb->dev->bus->uses_dma &&
+           (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
                return mon_dmapeek(ep->data, urb->transfer_dma, len);
+       }
 
        if (urb->transfer_buffer == NULL)
                return 'Z';     /* '0' would be not as pretty. */
@@ -146,6 +190,9 @@ static void mon_text_event(struct mon_re
 {
        struct mon_event_text *ep;
        unsigned int stamp;
+       struct usb_iso_packet_descriptor *fp;
+       struct mon_iso_desc *dp;
+       int i, ndesc;
 
        stamp = mon_get_timestamp();
 
@@ -158,12 +205,36 @@ static void mon_text_event(struct mon_re
        ep->type = ev_type;
        ep->pipe = urb->pipe;
        ep->id = (unsigned long) urb;
+       ep->busnum = urb->dev->bus->busnum;
        ep->tstamp = stamp;
        ep->length = (ev_type == 'S') ?
            urb->transfer_buffer_length : urb->actual_length;
        /* Collecting status makes debugging sense for submits, too */
        ep->status = urb->status;
 
+       if (usb_pipeint(urb->pipe)) {
+               ep->interval = urb->interval;
+       } else if (usb_pipeisoc(urb->pipe)) {
+               ep->interval = urb->interval;
+               ep->start_frame = urb->start_frame;
+               ep->error_count = urb->error_count;
+       }
+       ep->numdesc = urb->number_of_packets;
+       if (usb_pipeisoc(urb->pipe) && urb->number_of_packets > 0) {
+               if ((ndesc = urb->number_of_packets) > ISODESC_MAX)
+                       ndesc = ISODESC_MAX;
+               fp = urb->iso_frame_desc;
+               dp = ep->isodesc;
+               for (i = 0; i < ndesc; i++) {
+                       dp->status = fp->status;
+                       dp->offset = fp->offset;
+                       dp->length = (ev_type == 'S') ?
+                           fp->length : fp->actual_length;
+                       fp++;
+                       dp++;
+               }
+       }
+
        ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
        ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
                        rp->r.m_bus);
@@ -199,6 +270,7 @@ static void mon_text_error(void *data, s
        ep->type = 'E';
        ep->pipe = urb->pipe;
        ep->id = (unsigned long) urb;
+       ep->busnum = 0;
        ep->tstamp = 0;
        ep->length = 0;
        ep->status = error;
@@ -237,13 +309,11 @@ static struct mon_event_text *mon_text_f
 static int mon_text_open(struct inode *inode, struct file *file)
 {
        struct mon_bus *mbus;
-       struct usb_bus *ubus;
        struct mon_reader_text *rp;
        int rc;
 
        mutex_lock(&mon_lock);
        mbus = inode->i_private;
-       ubus = mbus->u_bus;
 
        rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
        if (rp == NULL) {
@@ -267,8 +337,7 @@ static int mon_text_open(struct inode *i
        rp->r.rnf_error = mon_text_error;
        rp->r.rnf_complete = mon_text_complete;
 
-       snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
-           (long)rp);
+       snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp);
        rp->e_slab = kmem_cache_create(rp->slab_name,
            sizeof(struct mon_event_text), sizeof(long), 0,
            mon_text_ctor, NULL);
@@ -300,17 +369,75 @@ err_alloc:
  *   dd if=/dbg/usbmon/0t bs=10
  * Also, we do not allow seeks and do not bother advancing the offset.
  */
-static ssize_t mon_text_read(struct file *file, char __user *buf,
+static ssize_t mon_text_read_t(struct file *file, char __user *buf,
+                               size_t nbytes, loff_t *ppos)
+{
+       struct mon_reader_text *rp = file->private_data;
+       struct mon_event_text *ep;
+       struct mon_text_ptr ptr;
+
+       if (IS_ERR(ep = mon_text_read_wait(rp, file)))
+               return PTR_ERR(ep);
+       mutex_lock(&rp->printf_lock);
+       ptr.cnt = 0;
+       ptr.pbuf = rp->printf_buf;
+       ptr.limit = rp->printf_size;
+
+       mon_text_read_head_t(rp, &ptr, ep);
+       mon_text_read_statset(rp, &ptr, ep);
+       ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
+           " %d", ep->length);
+       mon_text_read_data(rp, &ptr, ep);
+
+       if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
+               ptr.cnt = -EFAULT;
+       mutex_unlock(&rp->printf_lock);
+       kmem_cache_free(rp->e_slab, ep);
+       return ptr.cnt;
+}
+
+static ssize_t mon_text_read_u(struct file *file, char __user *buf,
                                size_t nbytes, loff_t *ppos)
 {
        struct mon_reader_text *rp = file->private_data;
+       struct mon_event_text *ep;
+       struct mon_text_ptr ptr;
+
+       if (IS_ERR(ep = mon_text_read_wait(rp, file)))
+               return PTR_ERR(ep);
+       mutex_lock(&rp->printf_lock);
+       ptr.cnt = 0;
+       ptr.pbuf = rp->printf_buf;
+       ptr.limit = rp->printf_size;
+
+       mon_text_read_head_u(rp, &ptr, ep);
+       if (ep->type == 'E') {
+               mon_text_read_statset(rp, &ptr, ep);
+       } else if (usb_pipeisoc(ep->pipe)) {
+               mon_text_read_isostat(rp, &ptr, ep);
+               mon_text_read_isodesc(rp, &ptr, ep);
+       } else if (usb_pipeint(ep->pipe)) {
+               mon_text_read_intstat(rp, &ptr, ep);
+       } else {
+               mon_text_read_statset(rp, &ptr, ep);
+       }
+       ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
+           " %d", ep->length);
+       mon_text_read_data(rp, &ptr, ep);
+
+       if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
+               ptr.cnt = -EFAULT;
+       mutex_unlock(&rp->printf_lock);
+       kmem_cache_free(rp->e_slab, ep);
+       return ptr.cnt;
+}
+
+static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp,
+    struct file *file)
+{
        struct mon_bus *mbus = rp->r.m_bus;
        DECLARE_WAITQUEUE(waita, current);
        struct mon_event_text *ep;
-       int cnt, limit;
-       char *pbuf;
-       char udir, utype;
-       int data_len, i;
 
        add_wait_queue(&rp->wait, &waita);
        set_current_state(TASK_INTERRUPTIBLE);
@@ -318,7 +445,7 @@ static ssize_t mon_text_read(struct file
                if (file->f_flags & O_NONBLOCK) {
                        set_current_state(TASK_RUNNING);
                        remove_wait_queue(&rp->wait, &waita);
-                       return -EWOULDBLOCK;    /* Same as EAGAIN in Linux */
+                       return ERR_PTR(-EWOULDBLOCK);
                }
                /*
                 * We do not count nwaiters, because ->release is supposed
@@ -327,17 +454,19 @@ static ssize_t mon_text_read(struct file
                schedule();
                if (signal_pending(current)) {
                        remove_wait_queue(&rp->wait, &waita);
-                       return -EINTR;
+                       return ERR_PTR(-EINTR);
                }
                set_current_state(TASK_INTERRUPTIBLE);
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&rp->wait, &waita);
+       return ep;
+}
 
-       mutex_lock(&rp->printf_lock);
-       cnt = 0;
-       pbuf = rp->printf_buf;
-       limit = rp->printf_size;
+static void mon_text_read_head_t(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+       char udir, utype;
 
        udir = usb_pipein(ep->pipe) ? 'i' : 'o';
        switch (usb_pipetype(ep->pipe)) {
@@ -346,13 +475,38 @@ static ssize_t mon_text_read(struct file
        case PIPE_CONTROL:      utype = 'C'; break;
        default: /* PIPE_BULK */  utype = 'B';
        }
-       cnt += snprintf(pbuf + cnt, limit - cnt,
+       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
            "%lx %u %c %c%c:%03u:%02u",
            ep->id, ep->tstamp, ep->type,
-           utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+           utype, udir,
+           usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+}
+
+static void mon_text_read_head_u(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+       char udir, utype;
+
+       udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+       switch (usb_pipetype(ep->pipe)) {
+       case PIPE_ISOCHRONOUS:  utype = 'Z'; break;
+       case PIPE_INTERRUPT:    utype = 'I'; break;
+       case PIPE_CONTROL:      utype = 'C'; break;
+       default: /* PIPE_BULK */  utype = 'B';
+       }
+       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+           "%lx %u %c %c%c:%d:%03u:%u",
+           ep->id, ep->tstamp, ep->type,
+           utype, udir,
+           ep->busnum, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+}
+
+static void mon_text_read_statset(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
 
        if (ep->setup_flag == 0) {   /* Setup packet is present and captured */
-               cnt += snprintf(pbuf + cnt, limit - cnt,
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
                    " s %02x %02x %04x %04x %04x",
                    ep->setup[0],
                    ep->setup[1],
@@ -360,40 +514,86 @@ static ssize_t mon_text_read(struct file
                    (ep->setup[5] << 8) | ep->setup[4],
                    (ep->setup[7] << 8) | ep->setup[6]);
        } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */
-               cnt += snprintf(pbuf + cnt, limit - cnt,
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
                    " %c __ __ ____ ____ ____", ep->setup_flag);
        } else {                     /* No setup for this kind of URB */
-               cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status);
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+                   " %d", ep->status);
        }
-       cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length);
+}
+
+static void mon_text_read_intstat(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+           " %d:%d", ep->status, ep->interval);
+}
+
+static void mon_text_read_isostat(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+       if (ep->type == 'S') {
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+                   " %d:%d:%d", ep->status, ep->interval, ep->start_frame);
+       } else {
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+                   " %d:%d:%d:%d",
+                   ep->status, ep->interval, ep->start_frame, ep->error_count);
+       }
+}
+
+static void mon_text_read_isodesc(struct mon_reader_text *rp,
+       struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+       int ndesc;      /* Display this many */
+       int i;
+       const struct mon_iso_desc *dp;
+
+       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+           " %d", ep->numdesc);
+       ndesc = ep->numdesc;
+       if (ndesc > ISODESC_MAX)
+               ndesc = ISODESC_MAX;
+       if (ndesc < 0)
+               ndesc = 0;
+       dp = ep->isodesc;
+       for (i = 0; i < ndesc; i++) {
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+                   " %d:%u:%u", dp->status, dp->offset, dp->length);
+               dp++;
+       }
+}
+
+static void mon_text_read_data(struct mon_reader_text *rp,
+    struct mon_text_ptr *p, const struct mon_event_text *ep)
+{
+       int data_len, i;
 
        if ((data_len = ep->length) > 0) {
                if (ep->data_flag == 0) {
-                       cnt += snprintf(pbuf + cnt, limit - cnt, " =");
+                       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+                           " =");
                        if (data_len >= DATA_MAX)
                                data_len = DATA_MAX;
                        for (i = 0; i < data_len; i++) {
                                if (i % 4 == 0) {
-                                       cnt += snprintf(pbuf + cnt, limit - cnt,
+                                       p->cnt += snprintf(p->pbuf + p->cnt,
+                                           p->limit - p->cnt,
                                            " ");
                                }
-                               cnt += snprintf(pbuf + cnt, limit - cnt,
+                               p->cnt += snprintf(p->pbuf + p->cnt,
+                                   p->limit - p->cnt,
                                    "%02x", ep->data[i]);
                        }
-                       cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+                       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+                           "\n");
                } else {
-                       cnt += snprintf(pbuf + cnt, limit - cnt,
+                       p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
                            " %c\n", ep->data_flag);
                }
        } else {
-               cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+               p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n");
        }
-
-       if (copy_to_user(buf, rp->printf_buf, cnt))
-               cnt = -EFAULT;
-       mutex_unlock(&rp->printf_lock);
-       kmem_cache_free(rp->e_slab, ep);
-       return cnt;
 }
 
 static int mon_text_release(struct inode *inode, struct file *file)
@@ -439,34 +639,46 @@ static int mon_text_release(struct inode
        return 0;
 }
 
-static const struct file_operations mon_fops_text = {
+static const struct file_operations mon_fops_text_t = {
        .owner =        THIS_MODULE,
        .open =         mon_text_open,
        .llseek =       no_llseek,
-       .read =         mon_text_read,
-       /* .write =     mon_text_write, */
-       /* .poll =              mon_text_poll, */
-       /* .ioctl =     mon_text_ioctl, */
+       .read =         mon_text_read_t,
        .release =      mon_text_release,
 };
 
-int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
+static const struct file_operations mon_fops_text_u = {
+       .owner =        THIS_MODULE,
+       .open =         mon_text_open,
+       .llseek =       no_llseek,
+       .read =         mon_text_read_u,
+       .release =      mon_text_release,
+};
+
+int mon_text_add(struct mon_bus *mbus, int busnum)
 {
        struct dentry *d;
        enum { NAMESZ = 10 };
        char name[NAMESZ];
        int rc;
 
-       rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
+       rc = snprintf(name, NAMESZ, "%dt", busnum);
        if (rc <= 0 || rc >= NAMESZ)
                goto err_print_t;
-       d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text);
+       d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t);
        if (d == NULL)
                goto err_create_t;
        mbus->dent_t = d;
 
-       /* XXX The stats do not belong to here (text API), but oh well... */
-       rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
+       rc = snprintf(name, NAMESZ, "%du", busnum);
+       if (rc <= 0 || rc >= NAMESZ)
+               goto err_print_u;
+       d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_u);
+       if (d == NULL)
+               goto err_create_u;
+       mbus->dent_u = d;
+
+       rc = snprintf(name, NAMESZ, "%ds", busnum);
        if (rc <= 0 || rc >= NAMESZ)
                goto err_print_s;
        d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_stat);
@@ -478,6 +690,10 @@ int mon_text_add(struct mon_bus *mbus, c
 
 err_create_s:
 err_print_s:
+       debugfs_remove(mbus->dent_u);
+       mbus->dent_u = NULL;
+err_create_u:
+err_print_u:
        debugfs_remove(mbus->dent_t);
        mbus->dent_t = NULL;
 err_create_t:
@@ -487,6 +703,7 @@ err_print_t:
 
 void mon_text_del(struct mon_bus *mbus)
 {
+       debugfs_remove(mbus->dent_u);
        debugfs_remove(mbus->dent_t);
        debugfs_remove(mbus->dent_s);
 }
diff -urp -X dontdiff linux-2.6/drivers/usb/mon/usb_mon.h 
linux-2.6.21-mon/drivers/usb/mon/usb_mon.h
--- linux-2.6/drivers/usb/mon/usb_mon.h 2007-03-01 16:17:48.000000000 -0800
+++ linux-2.6.21-mon/drivers/usb/mon/usb_mon.h  2007-03-05 14:59:35.000000000 
-0800
@@ -20,9 +20,11 @@ struct mon_bus {
        struct usb_bus *u_bus;
 
        int text_inited;
+       int bin_inited;
        struct dentry *dent_s;          /* Debugging file */
        struct dentry *dent_t;          /* Text interface file */
-       int uses_dma;
+       struct dentry *dent_u;          /* Second text interface file */
+       struct device *classdev;        /* Device in usbmon class */
 
        /* Ref */
        int nreaders;                   /* Under mon_lock AND mbus->lock */
@@ -52,9 +54,10 @@ void mon_reader_del(struct mon_bus *mbus
 
 struct mon_bus *mon_bus_lookup(unsigned int num);
 
-int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus);
+int /*bool*/ mon_text_add(struct mon_bus *mbus, int busnum);
 void mon_text_del(struct mon_bus *mbus);
-// void mon_bin_add(struct mon_bus *);
+int /*bool*/ mon_bin_add(struct mon_bus *mbus, int busnum);
+void mon_bin_del(struct mon_bus *mbus);
 
 int __init mon_text_init(void);
 void mon_text_exit(void);
@@ -81,4 +84,6 @@ extern struct mutex mon_lock;
 
 extern const struct file_operations mon_fops_stat;
 
+extern struct mon_bus mon_bus0;                /* Only for redundant checks */
+
 #endif /* __USB_MON_H */

-------------------------------------------------------------------------
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

Reply via email to