4 * Decodes traces captured by 'usbsnoop'
5 * (http://benoit.papillault.free.fr/usbsnoop/index.php)
7 * See usbsnoop.txt for details.
11 * Copyright (C) 2004-2005 Adam Kropelin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of version 2 of the GNU General
15 * Public License as published by the Free Software Foundation.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public
23 * License along with this program; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
33 char line
[MAX_LINE
] = "";
50 FUNC_GET_DESC_FROM_IFACE
,
74 unsigned long reserved
;
75 unsigned long request
;
92 struct rpt
* rpts
= NULL
;
95 [197 ms] >>> URB 1 going down >>>
96 -- URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
97 TransferBufferLength = 00000012
98 TransferBuffer = 864c9208
99 TransferBufferMDL = 00000000
101 DescriptorType = 00000001 (USB_DEVICE_DESCRIPTOR_TYPE)
102 LanguageId = 00000000
103 [203 ms] UsbSnoop - MyInternalIOCTLCompletion(f7b91db0) : fido=00000000, Irp=863df850, Context=86405d10, IRQL=2
105 [203 ms] <<< URB 1 coming back <<<
106 -- URB_FUNCTION_CONTROL_TRANSFER:
107 PipeHandle = 863e4150
108 TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
109 TransferBufferLength = 00000012
110 TransferBuffer = 864c9208
111 TransferBufferMDL = 8640f108
112 00000000: 12 01 10 01 00 00 00 08 1d 05 02 00 06 00 03 01
118 [59563 ms] >>> URB 346 going down >>>
119 -- URB_FUNCTION_CLASS_INTERFACE:
120 TransferFlags = 00000001 (USBD_TRANSFER_DIRECTION_IN, ~USBD_SHORT_TRANSFER_OK)
121 TransferBufferLength = 00000005
122 TransferBuffer = f7f12ba0
123 TransferBufferMDL = 00000000
125 RequestTypeReservedBits = 00000022
129 [59567 ms] UsbSnoop - MyInternalIOCTLCompletion(f7b91db0) : fido=86397288, Irp=85ff4b40, Context=85f4b3d8, IRQL=2
130 [59567 ms] <<< URB 346 coming back <<<
131 -- URB_FUNCTION_CONTROL_TRANSFER:
132 PipeHandle = 863e4150
133 TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
134 TransferBufferLength = 00000002
135 TransferBuffer = f7f12ba0
136 TransferBufferMDL = 85f102f0
140 00000000: a1 01 2f 03 00 00 05 00
145 return !!fgets(line
, sizeof(line
), file
);
152 if (line
[0] == '[' && strstr(line
, " URB ") &&
153 (strstr(line
, "going down") || strstr(line
, "coming back")))
158 while( fetch_line() );
163 int init_urb(struct urb
* urb
)
165 memset(urb
, 0, sizeof(*urb
));
170 urb
->time
= atoi(line
+1);
172 if (strstr(line
, "going down"))
173 urb
->dir
= DIR_TO_DEVICE
;
174 else if(strstr(line
, "coming back"))
175 urb
->dir
= DIR_FROM_DEVICE
;
177 urb
->dir
= DIR_UNKNOWN
;
179 urb
->seq
= atoi(strstr(line
,"URB ")+4);
184 unsigned long get_hex_value()
186 char* ptr
= strchr(line
, '=');
190 return strtoul(ptr
+2, NULL
, 16);
193 unsigned char* parse_data_dump(int len
)
198 unsigned char* data
= (unsigned char *)malloc(len
);
204 if ((count
% 16) == 0)
215 ptr
= strchr(line
, ':');
225 data
[count
++] = strtoul(ptr
, NULL
, 16);
232 void parse_urb_body(struct urb
* urb
)
234 int setup_packet
= 0;
241 if (strstr(line
, "TransferBufferLength"))
243 urb
->len
= get_hex_value();
245 else if (strstr(line
, "TransferFlags"))
247 urb
->flags
= get_hex_value();
249 else if (strstr(line
, "Index"))
251 urb
->index
= get_hex_value();
253 else if (strstr(line
, "DescriptorType"))
255 urb
->type
= get_hex_value();
257 else if (strstr(line
, "RequestTypeReservedBits"))
259 urb
->reserved
= get_hex_value();
261 else if (strstr(line
, "Request"))
263 urb
->request
= get_hex_value();
265 else if (strstr(line
, "Value"))
267 urb
->value
= get_hex_value();
269 else if (strstr(line
, "SetupPacket"))
273 else if (strstr(line
, "00000000:"))
275 if (!setup_packet
&& !urb
->data
)
276 urb
->data
= parse_data_dump(urb
->len
);
278 else if (strstr(line
, "-- URB_FUNCTION_"))
280 if (strstr(line
, "URB_FUNCTION_CONTROL_TRANSFER"))
281 urb
->func
= FUNC_CONTROL_TXFER
;
282 else if (strstr(line
, "URB_FUNCTION_CLASS_INTERFACE"))
283 urb
->func
= FUNC_CLASS_INTERFACE
;
284 else if (strstr(line
, "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"))
285 urb
->func
= FUNC_GET_DESC
;
286 else if (strstr(line
, "URB_FUNCTION_SELECT_CONFIGURATION"))
287 urb
->func
= FUNC_SELECT_CONFIG
;
288 else if (strstr(line
, "URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"))
289 urb
->func
= FUNC_GET_DESC_FROM_IFACE
;
290 else if (strstr(line
, "URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"))
291 urb
->func
= FUNC_BULK_TXFER
;
292 else if (strstr(line
, "URB_FUNCTION_RESET_PIPE"))
293 urb
->func
= FUNC_RESET_PIPE
;
294 else if (strstr(line
, "URB_FUNCTION_ABORT_PIPE"))
295 urb
->func
= FUNC_ABORT_PIPE
;
298 urb
->func
= FUNC_UNKNOWN
;
299 printf("Unknown FUNC: %s\n", line
);
306 void free_urb(struct urb
* urb
)
311 void print_urb(struct urb
* urb
)
314 printf("[%08d ms] %05d %c ", urb
->time
, urb
->seq
,
315 (urb
->dir
== DIR_TO_DEVICE
) ? '>' : (urb
->dir
== DIR_FROM_DEVICE
) ? '<' : '?');
317 printf("req=%04lx value=%04lx", urb
->request
, urb
->value
);
322 for(x
=0; x
<urb
->len
; x
++)
324 printf( "%02x", urb
->data
[x
] );
334 struct rpt
* find_report_by_seq(int seq
)
336 struct rpt
* rpt
= rpts
;
349 struct rpt
* find_report_by_id(unsigned char id
)
351 struct rpt
* rpt
= rpts
;
364 void del_report(struct urb
* urb
)
366 unsigned char id
= urb
->data
[0];
367 struct rpt
* rpt
= rpts
;
368 struct rpt
** prev
= &rpts
;
386 void add_report(struct urb
* urb
)
394 id
= urb
->value
& 0xff;
396 if ((rpt
= find_report_by_id(id
)))
399 rpt
->value
= urb
->value
;
403 rpt
= (struct rpt
*)malloc(sizeof(*rpt
));
404 memset(rpt
, 0, sizeof(*rpt
));
408 rpt
->value
= urb
->value
;
414 int check_and_update_report(struct urb
* urb
)
418 rpt
= find_report_by_seq(urb
->seq
);
422 if (rpt
->data
&& !memcmp(rpt
->data
, urb
->data
+1, urb
->len
-1))
426 rpt
->len
= urb
->len
-1;
427 rpt
->data
= (unsigned char *)malloc(rpt
->len
);
428 memcpy(rpt
->data
, urb
->data
+1, rpt
->len
);
433 void display_report(struct urb
* urb
)
435 unsigned long data
= 0;
439 n
= printf( "[%04d s] %05d %c %s 0x%02x (%03u) ",
440 urb
->time
/1000, urb
->seq
, urb
->func
== FUNC_BULK_TXFER
? '*' : ' ',
441 urb
->dir
==DIR_TO_DEVICE
? "WRITE" : " READ", urb
->data
[0], urb
->data
[0]);
446 data
= (data
<< 8) | urb
->data
[4];
448 data
= (data
<< 8) | urb
->data
[3];
450 data
= (data
<< 8) | urb
->data
[2];
452 data
= (data
<< 8) | urb
->data
[1];
453 sprintf(buf
, "%0*lx", (int)(urb
->len
-1)*2, data
);
454 n
+= printf( "%8s (%lu)", buf
, data
);
458 n
+= printf( "-------- (----------)" );
462 printf( "%*c", 55-n
, ' ');
463 for (n
=0; n
<urb
->len
-1; n
++)
464 printf("%02x ", urb
->data
[n
+1]);
469 void update_reports(struct urb
* urb
)
471 if (urb
->dir
== DIR_TO_DEVICE
)
473 // Only care about class requests
474 if (urb
->func
!= FUNC_CLASS_INTERFACE
)
477 if (urb
->request
== REQ_GET_REPORT
)
481 else if (urb
->request
== REQ_SET_REPORT
)
489 if (urb
->func
== FUNC_CONTROL_TXFER
)
491 if (check_and_update_report(urb
))
494 else if (urb
->data
&& urb
->func
== FUNC_BULK_TXFER
)
497 if (check_and_update_report(urb
))
503 int main(int argc
, char* argv
[])
509 while(init_urb(&urb
))
511 parse_urb_body(&urb
);
513 update_reports(&urb
);