extended urb information for binary API again

Paolo Abeni <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Hello,

I tried to address the issues in my latest patch for implementing the
extended binary API, while keeping the header size to 48 bytes. This is
the result. 

All the data fields recognized by usbmon are now in host byte order. The
'xfer_flags' field is now present also for submit events (reusing the
'status' field which should not be significant for submit event,
according to 'Linux device drivers 3rd edition').

The patch is against linux 2.6.21.1

--
Index: linux-vanilla/drivers/usb/mon/mon_bin.c
===================================================================
--- linux-vanilla.orig/drivers/usb/mon/mon_bin.c
+++ linux-vanilla/drivers/usb/mon/mon_bin.c
@@ -3,7 +3,7 @@
  *
  * This is a binary format reader.
  *
- * Copyright (C) 2006 Paolo Abeni ([email protected])
+ * Copyright (C) 2006,2007 Paolo Abeni ([email protected])
  * Copyright (C) 2006,2007 Pete Zaitcev ([email protected])
  */
 
@@ -72,6 +72,15 @@
 #define BUFF_MIN     CHUNK_ALIGN(8*1024)
 
 /*
+ * The event union type contained into the event 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,27 @@ 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;
+	union {
+		int status;	/* for C-type events */
+		unsigned int setup_xfer_flags; /* only for S-type events */
+	};
 	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 complete_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 +192,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 +413,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 = 0;
+	ep->len_urb = datalen;
+	ep->len_cap = datalen;
+	ep->flag_data = 0;
+	ep->flag_hdr = MON_BIN_ISO;
+	ep->iso_hdr.start_frame = urb->start_frame;
+	ep->iso_hdr.number_of_packets = 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 = urb->iso_frame_desc[i].offset;
+		pd->length = urb->iso_frame_desc[i].length;
+		pd->actual_length = urb->iso_frame_desc[i].actual_length;
+		pd->status = urb->iso_frame_desc[i].status;
+	}
+}
+
 static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
     char ev_type)
 {
@@ -452,7 +526,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 accordingly to the effective type of 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 +537,17 @@ static void mon_bin_event(struct mon_rea
 	} else {
 		ep->flag_data = data_tag;
 	}
+	if (ev_type == 'C') {
+		ep->compl_hdr.complete_xfer_flags = urb->transfer_flags;
+		/* this field is meaningful only for ISO and interrupt transfer*/
+		ep->compl_hdr.interval = urb->interval;
+		ep->flag_hdr = MON_BIN_XFER;
+	} else {
+		ep->setup_xfer_flags = urb->transfer_flags;
+		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 +594,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.complete_xfer_flags = urb->transfer_flags;
+	/* this field is meaningful only for ISO and interrupt transfer*/
+	ep->compl_hdr.interval = urb->interval;
 
 	spin_unlock_irqrestore(&rp->b_lock, flags);
 


 
 
 --
 Email.it, the professional e-mail, gratis per te: http://www.email.it/f
 
 Sponsor:
 La Cronaca del Carnevale di Ivrea 2007 visto su www.localport.it: per conoscere il Carnevale, per rivivere l’edizione 2007. Acquistalo on line
 Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=6431&d=4-5

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.