hello,

I just noticed that the patch I posted in the previous message was
broken due to line wrapping, so I re-post it. 

Some more details about the patch: the urb information are split across
multiple events. For example, for Control transfer, the 'S' event carry
the setup header, and the 'C' event carry the transfer flags. For ISO
transfer the 'C' event carry the transfer flags and the interval and a
newly introduced 'P' event carry the start_frame, the number of packets
and iso packet descriptors for all the packets used by this transfer.

This scenario require the user level usbmon reader to maintain some kind
of per transfer status in order to fully reconstruct the transfer
information.

ciao,

Paolo

--
Index: linux/drivers/usb/mon/mon_bin.c
===================================================================
--- linux.orig/drivers/usb/mon/mon_bin.c
+++ linux/drivers/usb/mon/mon_bin.c
@@ -72,6 +72,15 @@
 #define BUFF_MIN     CHUNK_ALIGN(8*1024)
 
 /*
+ * The event union type contained into the event struct struct is 
+ * specified by the flag_hdr field. If it does not hold any of the following
+ * values it's content are unspecified
+ */
+#define MON_BIN_SETUP 0x00
+#define MON_BIN_XFER  0x01
+#define MON_BIN_ISO   0x02
+
+/*
  * The per-event API header (2 per URB).
  *
  * This structure is seen in userland as defined by the documentation.
@@ -83,14 +92,24 @@ struct mon_bin_hdr {
        unsigned char epnum;    /* Endpoint number and transfer direction */
        unsigned char devnum;   /* Device address */
        unsigned short busnum;  /* Bus number */
-       char flag_setup;
+       char flag_hdr;
        char flag_data;
        s64 ts_sec;             /* gettimeofday */
        s32 ts_usec;            /* gettimeofday */
        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 {
+                       int interval;
+                       unsigned int xfer_flags;
+               } compl_hdr;    /* For C/E-Type */
+               struct {
+                       int start_frame;
+                       int number_of_packets;
+               } iso_hdr;      /* For ISO P-Type */ 
+       };
 };
 
 /* per file statistic */
@@ -170,6 +189,12 @@ static inline struct mon_bin_hdr *MON_OF
            (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
 }
 
+static inline struct usb_iso_packet_descriptor* MON_OFF2DSC(
+                       const struct mon_reader_bin *rp, unsigned int offset)
+{
+       return (struct usb_iso_packet_descriptor*)
+               (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
+}
 #define MON_RING_EMPTY(rp)     ((rp)->b_cnt == 0)
 
 static struct class *mon_bin_class;
@@ -385,6 +410,52 @@ static char mon_bin_get_data(const struc
        return 0;
 }
 
+/* create extra event for ISO frames info; must be called with rp->b_lock hold 
*/
+static void mon_bin_iso_event(struct mon_reader_bin *rp, struct urb *urb,
+       struct timeval* ts)
+{
+       int i,datalen;
+       unsigned int offset;
+       struct mon_bin_hdr *ep;
+
+       datalen = urb->number_of_packets * sizeof(struct 
usb_iso_packet_descriptor);
+       offset = mon_buff_area_alloc_contiguous(rp, PKT_SIZE + datalen);
+       /* XXXX this is not a real event lost, should we increment rp->cnt_lost 
?!?*/
+       if (offset == ~0)
+               return;
+
+       ep = MON_OFF2HDR(rp, offset);
+       if ((offset += PKT_SIZE) >= rp->b_size) 
+               offset = 0;
+       ep->type = 'P';
+       ep->xfer_type = usb_pipetype(urb->pipe);
+       ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
+       ep->devnum = usb_pipedevice(urb->pipe);
+       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 = datalen;
+       ep->len_cap = datalen;
+       ep->flag_data = 0;
+       ep->flag_hdr = MON_BIN_ISO;
+       ep->iso_hdr.start_frame = cpu_to_be32(urb->start_frame);
+       ep->iso_hdr.number_of_packets = cpu_to_be32(urb->number_of_packets);
+       for (i = 0; i< ep->iso_hdr.number_of_packets; ++i) {
+               struct usb_iso_packet_descriptor* pd = MON_OFF2DSC(rp, offset);
+               offset = (offset + sizeof(struct usb_iso_packet_descriptor)) %
+                                       rp->b_size;
+
+               /* the frame data is going into the event data. For consistency
+                * with 'real' events keep this data in big endian byte order */
+               pd->offset = cpu_to_be32(urb->iso_frame_desc[i].offset);
+               pd->length = cpu_to_be32(urb->iso_frame_desc[i].length);
+               pd->actual_length = 
cpu_to_be32(urb->iso_frame_desc[i].actual_length);
+               pd->status = cpu_to_be32(urb->iso_frame_desc[i].status);
+       }
+}
+
 static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
     char ev_type)
 {
@@ -452,7 +523,8 @@ static void mon_bin_event(struct mon_rea
        ep->len_urb = urb_length;
        ep->len_cap = length;
 
-       ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
+       /* should we set flag_data accoringly to effective type this event 
union ?!?*/
+       ep->flag_hdr = 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' */
@@ -462,6 +534,14 @@ static void mon_bin_event(struct mon_rea
        } else {
                ep->flag_data = data_tag;
        }
+       if (ev_type == 'C') {
+               ep->compl_hdr.xfer_flags = cpu_to_be32(urb->transfer_flags);
+               /* this field is meaningful only for ISO and interrupt 
transfer*/
+               ep->compl_hdr.interval = cpu_to_be32(urb->interval);
+               ep->flag_hdr = MON_BIN_XFER;
+       } else if (usb_pipeisoc(urb->pipe)) 
+               /* add extra info for iso frames only on submit event */
+               mon_bin_iso_event(rp, urb, &ts);
 
        spin_unlock_irqrestore(&rp->b_lock, flags);
 
@@ -508,8 +588,11 @@ static void mon_bin_error(void *data, st
        ep->id = (unsigned long) urb;
        ep->status = error;
 
-       ep->flag_setup = '-';
+       ep->flag_hdr = MON_BIN_XFER;
        ep->flag_data = 'E';
+       ep->compl_hdr.xfer_flags = cpu_to_be32(urb->transfer_flags);
+       /* this field is meaningful only for ISO and interrupt transfer*/
+       ep->compl_hdr.interval = cpu_to_be32(urb->interval);
 
        spin_unlock_irqrestore(&rp->b_lock, flags);
  

 
 
 --
 Email.it, the professional e-mail, gratis per te: http://www.email.it/f
 
 Sponsor:
 Fai crescere i tuoi sogni. Prestiti semplici e veloci
* Rate da 20 euro al mese
 Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=6334&d=29-3

-------------------------------------------------------------------------
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
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to