diff options
author | Pete Zaitcev <zaitcev@redhat.com> | 2005-06-25 17:32:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-07-12 14:52:55 -0400 |
commit | ae0d6cceb20eec57e7196c22999c62c465ffd5bf (patch) | |
tree | ba6b822e410af8621dc6f42bf0792b9eece2bbc6 | |
parent | ead99eb00190a274e3b3666ecd431be12c2b7888 (diff) |
[PATCH] USB: Patch to make usbmon to print control setup packets
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 <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | Documentation/usb/usbmon.txt | 29 | ||||
-rw-r--r-- | drivers/usb/mon/mon_text.c | 48 |
2 files changed, 64 insertions, 13 deletions
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 2f8431f92b77..f1896ee3bb2a 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt | |||
@@ -101,6 +101,13 @@ Here is the list of words, from left to right: | |||
101 | or 3 and 2 positions, correspondingly. | 101 | or 3 and 2 positions, correspondingly. |
102 | - URB Status. This field makes no sense for submissions, but is present | 102 | - URB Status. This field makes no sense for submissions, but is present |
103 | to help scripts with parsing. In error case, it contains the error code. | 103 | to help scripts with parsing. In error case, it contains the error code. |
104 | In case of a setup packet, it contains a Setup Tag. If scripts read a number | ||
105 | in this field, the proceed to read Data Length. Otherwise, they read | ||
106 | the setup packet before reading the Data Length. | ||
107 | - Setup packet, if present, consists of 5 words: one of each for bmRequestType, | ||
108 | bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0. | ||
109 | These words are safe to decode if Setup Tag was 's'. Otherwise, the setup | ||
110 | packet was present, but not captured, and the fields contain filler. | ||
104 | - Data Length. This is the actual length in the URB. | 111 | - Data Length. This is the actual length in the URB. |
105 | - Data tag. The usbmon may not always capture data, even if length is nonzero. | 112 | - Data tag. The usbmon may not always capture data, even if length is nonzero. |
106 | Only if tag is '=', the data words are present. | 113 | Only if tag is '=', the data words are present. |
@@ -125,25 +132,31 @@ class ParsedLine { | |||
125 | String data_str = st.nextToken(); | 132 | String data_str = st.nextToken(); |
126 | int len = data_str.length() / 2; | 133 | int len = data_str.length() / 2; |
127 | int i; | 134 | int i; |
135 | int b; // byte is signed, apparently?! XXX | ||
128 | for (i = 0; i < len; i++) { | 136 | for (i = 0; i < len; i++) { |
129 | data[data_len] = Byte.parseByte( | 137 | // data[data_len] = Byte.parseByte( |
130 | data_str.substring(i*2, i*2 + 2), | 138 | // data_str.substring(i*2, i*2 + 2), |
131 | 16); | 139 | // 16); |
140 | b = Integer.parseInt( | ||
141 | data_str.substring(i*2, i*2 + 2), | ||
142 | 16); | ||
143 | if (b >= 128) | ||
144 | b *= -1; | ||
145 | data[data_len] = (byte) b; | ||
132 | data_len++; | 146 | data_len++; |
133 | } | 147 | } |
134 | } | 148 | } |
135 | } | 149 | } |
136 | } | 150 | } |
137 | 151 | ||
138 | This format is obviously deficient. For example, the setup packet for control | 152 | This format may be changed in the future. |
139 | transfers is not delivered. This will change in the future. | ||
140 | 153 | ||
141 | Examples: | 154 | Examples: |
142 | 155 | ||
143 | An input control transfer to get a port status: | 156 | An input control transfer to get a port status. |
144 | 157 | ||
145 | d74ff9a0 2640288196 S Ci:001:00 -115 4 < | 158 | d5ea89a0 3575914555 S Ci:001:00 s a3 00 0000 0003 0004 4 < |
146 | d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100 | 159 | d5ea89a0 3575914560 C Ci:001:00 0 4 = 01050000 |
147 | 160 | ||
148 | An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper | 161 | An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper |
149 | to a storage device at address 5: | 162 | to a storage device at address 5: |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 755a4570477f..26266b30028e 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -19,11 +19,16 @@ | |||
19 | #define DATA_MAX 32 | 19 | #define DATA_MAX 32 |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * Defined by USB 2.0 clause 9.3, table 9.2. | ||
23 | */ | ||
24 | #define SETUP_MAX 8 | ||
25 | |||
26 | /* | ||
22 | * This limit exists to prevent OOMs when the user process stops reading. | 27 | * This limit exists to prevent OOMs when the user process stops reading. |
23 | */ | 28 | */ |
24 | #define EVENT_MAX 25 | 29 | #define EVENT_MAX 25 |
25 | 30 | ||
26 | #define PRINTF_DFL 120 | 31 | #define PRINTF_DFL 130 |
27 | 32 | ||
28 | struct mon_event_text { | 33 | struct mon_event_text { |
29 | struct list_head e_link; | 34 | struct list_head e_link; |
@@ -33,7 +38,9 @@ struct mon_event_text { | |||
33 | unsigned int tstamp; | 38 | unsigned int tstamp; |
34 | int length; /* Depends on type: xfer length or act length */ | 39 | int length; /* Depends on type: xfer length or act length */ |
35 | int status; | 40 | int status; |
41 | char setup_flag; | ||
36 | char data_flag; | 42 | char data_flag; |
43 | unsigned char setup[SETUP_MAX]; | ||
37 | unsigned char data[DATA_MAX]; | 44 | unsigned char data[DATA_MAX]; |
38 | }; | 45 | }; |
39 | 46 | ||
@@ -64,6 +71,22 @@ static void mon_text_dtor(void *, kmem_cache_t *, unsigned long); | |||
64 | * This is called with the whole mon_bus locked, so no additional lock. | 71 | * This is called with the whole mon_bus locked, so no additional lock. |
65 | */ | 72 | */ |
66 | 73 | ||
74 | static inline char mon_text_get_setup(struct mon_event_text *ep, | ||
75 | struct urb *urb, char ev_type) | ||
76 | { | ||
77 | |||
78 | if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') | ||
79 | return '-'; | ||
80 | |||
81 | if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) | ||
82 | return 'D'; | ||
83 | if (urb->setup_packet == NULL) | ||
84 | return 'Z'; /* '0' would be not as pretty. */ | ||
85 | |||
86 | memcpy(ep->setup, urb->setup_packet, SETUP_MAX); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
67 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | 90 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, |
68 | int len, char ev_type) | 91 | int len, char ev_type) |
69 | { | 92 | { |
@@ -90,7 +113,6 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | |||
90 | 113 | ||
91 | /* | 114 | /* |
92 | * Bulk is easy to shortcut reliably. | 115 | * Bulk is easy to shortcut reliably. |
93 | * XXX Control needs setup packet taken. | ||
94 | * XXX Other pipe types need consideration. Currently, we overdo it | 116 | * XXX Other pipe types need consideration. Currently, we overdo it |
95 | * and collect garbage for them: better more than less. | 117 | * and collect garbage for them: better more than less. |
96 | */ | 118 | */ |
@@ -144,6 +166,7 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, | |||
144 | /* Collecting status makes debugging sense for submits, too */ | 166 | /* Collecting status makes debugging sense for submits, too */ |
145 | ep->status = urb->status; | 167 | ep->status = urb->status; |
146 | 168 | ||
169 | ep->setup_flag = mon_text_get_setup(ep, urb, ev_type); | ||
147 | ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type); | 170 | ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type); |
148 | 171 | ||
149 | rp->nevents++; | 172 | rp->nevents++; |
@@ -299,10 +322,25 @@ static ssize_t mon_text_read(struct file *file, char __user *buf, | |||
299 | default: /* PIPE_BULK */ utype = 'B'; | 322 | default: /* PIPE_BULK */ utype = 'B'; |
300 | } | 323 | } |
301 | cnt += snprintf(pbuf + cnt, limit - cnt, | 324 | cnt += snprintf(pbuf + cnt, limit - cnt, |
302 | "%lx %u %c %c%c:%03u:%02u %d %d", | 325 | "%lx %u %c %c%c:%03u:%02u", |
303 | ep->id, ep->tstamp, ep->type, | 326 | ep->id, ep->tstamp, ep->type, |
304 | utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe), | 327 | utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); |
305 | ep->status, ep->length); | 328 | |
329 | if (ep->setup_flag == 0) { /* Setup packet is present and captured */ | ||
330 | cnt += snprintf(pbuf + cnt, limit - cnt, | ||
331 | " s %02x %02x %04x %04x %04x", | ||
332 | ep->setup[0], | ||
333 | ep->setup[1], | ||
334 | (ep->setup[3] << 8) | ep->setup[2], | ||
335 | (ep->setup[5] << 8) | ep->setup[4], | ||
336 | (ep->setup[7] << 8) | ep->setup[6]); | ||
337 | } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */ | ||
338 | cnt += snprintf(pbuf + cnt, limit - cnt, | ||
339 | " %c __ __ ____ ____ ____", ep->setup_flag); | ||
340 | } else { /* No setup for this kind of URB */ | ||
341 | cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status); | ||
342 | } | ||
343 | cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length); | ||
306 | 344 | ||
307 | if ((data_len = ep->length) > 0) { | 345 | if ((data_len = ep->length) > 0) { |
308 | if (ep->data_flag == 0) { | 346 | if (ep->data_flag == 0) { |