Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Pete Zaitcev and committed by
Greg Kroah-Hartman
ae0d6cce ead99eb0

+64 -13
+21 -8
Documentation/usb/usbmon.txt
··· 101 101 or 3 and 2 positions, correspondingly. 102 102 - URB Status. This field makes no sense for submissions, but is present 103 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 111 - Data Length. This is the actual length in the URB. 105 112 - Data tag. The usbmon may not always capture data, even if length is nonzero. 106 113 Only if tag is '=', the data words are present. ··· 132 125 String data_str = st.nextToken(); 133 126 int len = data_str.length() / 2; 134 127 int i; 128 + int b; // byte is signed, apparently?! XXX 135 129 for (i = 0; i < len; i++) { 136 - data[data_len] = Byte.parseByte( 137 - data_str.substring(i*2, i*2 + 2), 138 - 16); 130 + // data[data_len] = Byte.parseByte( 131 + // data_str.substring(i*2, i*2 + 2), 132 + // 16); 133 + b = Integer.parseInt( 134 + data_str.substring(i*2, i*2 + 2), 135 + 16); 136 + if (b >= 128) 137 + b *= -1; 138 + data[data_len] = (byte) b; 139 139 data_len++; 140 140 } 141 141 } 142 142 } 143 143 } 144 144 145 - This format is obviously deficient. For example, the setup packet for control 146 - transfers is not delivered. This will change in the future. 145 + This format may be changed in the future. 147 146 148 147 Examples: 149 148 150 - An input control transfer to get a port status: 149 + An input control transfer to get a port status. 151 150 152 - d74ff9a0 2640288196 S Ci:001:00 -115 4 < 153 - d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100 151 + d5ea89a0 3575914555 S Ci:001:00 s a3 00 0000 0003 0004 4 < 152 + d5ea89a0 3575914560 C Ci:001:00 0 4 = 01050000 154 153 155 154 An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper 156 155 to a storage device at address 5:
+43 -5
drivers/usb/mon/mon_text.c
··· 19 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 27 * This limit exists to prevent OOMs when the user process stops reading. 23 28 */ 24 29 #define EVENT_MAX 25 25 30 26 - #define PRINTF_DFL 120 31 + #define PRINTF_DFL 130 27 32 28 33 struct mon_event_text { 29 34 struct list_head e_link; ··· 38 33 unsigned int tstamp; 39 34 int length; /* Depends on type: xfer length or act length */ 40 35 int status; 36 + char setup_flag; 41 37 char data_flag; 38 + unsigned char setup[SETUP_MAX]; 42 39 unsigned char data[DATA_MAX]; 43 40 }; 44 41 ··· 71 64 * This is called with the whole mon_bus locked, so no additional lock. 72 65 */ 73 66 67 + static inline char mon_text_get_setup(struct mon_event_text *ep, 68 + struct urb *urb, char ev_type) 69 + { 70 + 71 + if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') 72 + return '-'; 73 + 74 + if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) 75 + return 'D'; 76 + if (urb->setup_packet == NULL) 77 + return 'Z'; /* '0' would be not as pretty. */ 78 + 79 + memcpy(ep->setup, urb->setup_packet, SETUP_MAX); 80 + return 0; 81 + } 82 + 74 83 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, 75 84 int len, char ev_type) 76 85 { ··· 113 90 114 91 /* 115 92 * Bulk is easy to shortcut reliably. 116 - * XXX Control needs setup packet taken. 117 93 * XXX Other pipe types need consideration. Currently, we overdo it 118 94 * and collect garbage for them: better more than less. 119 95 */ ··· 166 144 /* Collecting status makes debugging sense for submits, too */ 167 145 ep->status = urb->status; 168 146 147 + ep->setup_flag = mon_text_get_setup(ep, urb, ev_type); 169 148 ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type); 170 149 171 150 rp->nevents++; ··· 322 299 default: /* PIPE_BULK */ utype = 'B'; 323 300 } 324 301 cnt += snprintf(pbuf + cnt, limit - cnt, 325 - "%lx %u %c %c%c:%03u:%02u %d %d", 302 + "%lx %u %c %c%c:%03u:%02u", 326 303 ep->id, ep->tstamp, ep->type, 327 - utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe), 328 - ep->status, ep->length); 304 + utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); 305 + 306 + if (ep->setup_flag == 0) { /* Setup packet is present and captured */ 307 + cnt += snprintf(pbuf + cnt, limit - cnt, 308 + " s %02x %02x %04x %04x %04x", 309 + ep->setup[0], 310 + ep->setup[1], 311 + (ep->setup[3] << 8) | ep->setup[2], 312 + (ep->setup[5] << 8) | ep->setup[4], 313 + (ep->setup[7] << 8) | ep->setup[6]); 314 + } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */ 315 + cnt += snprintf(pbuf + cnt, limit - cnt, 316 + " %c __ __ ____ ____ ____", ep->setup_flag); 317 + } else { /* No setup for this kind of URB */ 318 + cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status); 319 + } 320 + cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length); 329 321 330 322 if ((data_len = ep->length) > 0) { 331 323 if (ep->data_flag == 0) {