Make usbmon to print Setup packets of Control transfers. This is useful
when debugging enumeration issues.

This is a change to the trace format which is not fully compatible.
A parser has to look at the data length word now. If that word is
a character like 's', read setup packet before proceeding with data.
I decided not to bump the API tag for this because not many such
parsers exist at this point.

Signed-off-by: Pete Zaitcev <[EMAIL PROTECTED]>

diff -urp -X dontdiff linux-2.6.12/Documentation/usb/usbmon.txt 
linux-2.6.12-lem/Documentation/usb/usbmon.txt
--- linux-2.6.12/Documentation/usb/usbmon.txt   2005-06-21 12:57:54.000000000 
-0700
+++ linux-2.6.12-lem/Documentation/usb/usbmon.txt       2005-06-25 
14:07:43.000000000 -0700
@@ -101,6 +101,13 @@ Here is the list of words, from left to 
   or 3 and 2 positions, correspondingly.
 - URB Status. This field makes no sense for submissions, but is present
   to help scripts with parsing. In error case, it contains the error code.
+  In case of a setup packet, it contains a Setup Tag. If scripts read a number
+  in this field, the proceed to read Data Length. Otherwise, they read
+  the setup packet before reading the Data Length.
+- Setup packet, if present, consists of 5 words: one of each for bmRequestType,
+  bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
+  These words are safe to decode if Setup Tag was 's'. Otherwise, the setup
+  packet was present, but not captured, and the fields contain filler.
 - Data Length. This is the actual length in the URB.
 - Data tag. The usbmon may not always capture data, even if length is nonzero.
   Only if tag is '=', the data words are present.
@@ -125,25 +132,31 @@ class ParsedLine {
                        String data_str = st.nextToken();
                        int len = data_str.length() / 2;
                        int i;
+                       int b;  // byte is signed, apparently?! XXX
                        for (i = 0; i < len; i++) {
-                               data[data_len] = Byte.parseByte(
-                                   data_str.substring(i*2, i*2 + 2),
-                                   16);
+                               // data[data_len] = Byte.parseByte(
+                               //     data_str.substring(i*2, i*2 + 2),
+                               //     16);
+                               b = Integer.parseInt(
+                                    data_str.substring(i*2, i*2 + 2),
+                                    16);
+                               if (b >= 128)
+                                       b *= -1;
+                               data[data_len] = (byte) b;
                                data_len++;
                        }
                }
        }
 }
 
-This format is obviously deficient. For example, the setup packet for control
-transfers is not delivered. This will change in the future.
+This format may be changed in the future.
 
 Examples:
 
-An input control transfer to get a port status:
+An input control transfer to get a port status.
 
-d74ff9a0 2640288196 S Ci:001:00 -115 4 <
-d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100
+d5ea89a0 3575914555 S Ci:001:00 s a3 00 0000 0003 0004 4 <
+d5ea89a0 3575914560 C Ci:001:00 0 4 = 01050000
 
 An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
 to a storage device at address 5:
diff -urp -X dontdiff linux-2.6.12/drivers/usb/mon/mon_text.c 
linux-2.6.12-lem/drivers/usb/mon/mon_text.c
--- linux-2.6.12/drivers/usb/mon/mon_text.c     2005-06-21 12:58:47.000000000 
-0700
+++ linux-2.6.12-lem/drivers/usb/mon/mon_text.c 2005-06-25 13:48:06.000000000 
-0700
@@ -19,11 +19,16 @@
 #define DATA_MAX  32
 
 /*
+ * Defined by USB 2.0 clause 9.3, table 9.2.
+ */
+#define SETUP_MAX  8
+
+/*
  * This limit exists to prevent OOMs when the user process stops reading.
  */
 #define EVENT_MAX  25
 
-#define PRINTF_DFL  120
+#define PRINTF_DFL  130
 
 struct mon_event_text {
        struct list_head e_link;
@@ -33,7 +38,9 @@ struct mon_event_text {
        unsigned int tstamp;
        int length;             /* Depends on type: xfer length or act length */
        int status;
+       char setup_flag;
        char data_flag;
+       unsigned char setup[SETUP_MAX];
        unsigned char data[DATA_MAX];
 };
 
@@ -64,6 +71,22 @@ static void mon_text_dtor(void *, kmem_c
  * This is called with the whole mon_bus locked, so no additional lock.
  */
 
+static inline char mon_text_get_setup(struct mon_event_text *ep,
+    struct urb *urb, char ev_type)
+{
+
+       if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
+               return '-';
+
+       if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+               return 'D';
+       if (urb->setup_packet == NULL)
+               return 'Z';     /* '0' would be not as pretty. */
+
+       memcpy(ep->setup, urb->setup_packet, SETUP_MAX);
+       return 0;
+}
+
 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb 
*urb,
     int len, char ev_type)
 {
@@ -90,7 +113,6 @@ static inline char mon_text_get_data(str
 
        /*
         * Bulk is easy to shortcut reliably. 
-        * XXX Control needs setup packet taken.
         * XXX Other pipe types need consideration. Currently, we overdo it
         * and collect garbage for them: better more than less.
         */
@@ -144,6 +166,7 @@ static void mon_text_event(struct mon_re
        /* Collecting status makes debugging sense for submits, too */
        ep->status = urb->status;
 
+       ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
        ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
 
        rp->nevents++;
@@ -299,10 +322,25 @@ static ssize_t mon_text_read(struct file
        default: /* PIPE_BULK */  utype = 'B';
        }
        cnt += snprintf(pbuf + cnt, limit - cnt,
-           "%lx %u %c %c%c:%03u:%02u %d %d",
+           "%lx %u %c %c%c:%03u:%02u",
            ep->id, ep->tstamp, ep->type,
-           utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe),
-           ep->status, ep->length);
+           utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
+
+       if (ep->setup_flag == 0) {   /* Setup packet is present and captured */
+               cnt += snprintf(pbuf + cnt, limit - cnt,
+                   " s %02x %02x %04x %04x %04x",
+                   ep->setup[0],
+                   ep->setup[1],
+                   (ep->setup[3] << 8) | ep->setup[2],
+                   (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,
+                   " %c __ __ ____ ____ ____", ep->setup_flag);
+       } else {                     /* No setup for this kind of URB */
+               cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status);
+       }
+       cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length);
 
        if ((data_len = ep->length) > 0) {
                if (ep->data_flag == 0) {


-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
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