UPS: apcupsd clean sources
[tomato.git] / release / src / router / apcupsd / examples / snoopdecode.c
blob04b14bdfcc3faf945859e295d164da11e67a539c
1 /*
2 * snoopdecode.c
4 * Decodes traces captured by 'usbsnoop'
5 * (http://benoit.papillault.free.fr/usbsnoop/index.php)
7 * See usbsnoop.txt for details.
8 */
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,
25 * MA 02111-1307, USA.
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
31 #define MAX_LINE 1024
33 char line[MAX_LINE] = "";
34 FILE* file;
36 enum
38 DIR_UNKNOWN = 0,
39 DIR_TO_DEVICE,
40 DIR_FROM_DEVICE
43 enum
45 FUNC_UNKNOWN = 0,
46 FUNC_CONTROL_TXFER,
47 FUNC_CLASS_INTERFACE,
48 FUNC_GET_DESC,
49 FUNC_SELECT_CONFIG,
50 FUNC_GET_DESC_FROM_IFACE,
51 FUNC_BULK_TXFER,
52 FUNC_RESET_PIPE,
53 FUNC_ABORT_PIPE,
56 enum
58 REQ_GET_REPORT = 1,
59 REQ_GET_IDLE = 2,
60 REQ_GET_PROTOCOL = 3,
61 REQ_SET_REPORT = 9,
62 REQ_SET_IDLE = 10,
63 REQ_SET_PROTOCOL = 11
66 struct urb
68 int seq;
69 unsigned long len;
70 unsigned char* data;
71 unsigned long flags;
72 unsigned long index;
73 unsigned long type;
74 unsigned long reserved;
75 unsigned long request;
76 unsigned long value;
77 int time;
78 int dir;
79 int func;
82 struct rpt
84 struct rpt* next;
85 unsigned char* data;
86 int seq;
87 unsigned short len;
88 unsigned char id;
89 unsigned long value;
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
100 Index = 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
113 00000010: 02 01
114 UrbLink = 00000000
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
124 UrbLink = 00000000
125 RequestTypeReservedBits = 00000022
126 Request = 00000001
127 Value = 0000032f
128 Index = 00000000
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
137 00000000: 2f 02
138 UrbLink = 00000000
139 SetupPacket =
140 00000000: a1 01 2f 03 00 00 05 00
143 int fetch_line()
145 return !!fgets(line, sizeof(line), file);
148 int find_urb()
152 if (line[0] == '[' && strstr(line, " URB ") &&
153 (strstr(line, "going down") || strstr(line, "coming back")))
155 return 1;
158 while( fetch_line() );
160 return 0;
163 int init_urb(struct urb* urb)
165 memset(urb, 0, sizeof(*urb));
167 if (!find_urb())
168 return 0;
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;
176 else
177 urb->dir = DIR_UNKNOWN;
179 urb->seq = atoi(strstr(line,"URB ")+4);
181 return 1;
184 unsigned long get_hex_value()
186 char* ptr = strchr(line, '=');
187 if (!ptr)
188 return 0xffff;
190 return strtoul(ptr+2, NULL, 16);
193 unsigned char* parse_data_dump(int len)
195 int count = 0;
196 char* ptr= NULL;
198 unsigned char* data = (unsigned char *)malloc(len);
199 if (!data)
200 return NULL;
202 while(count < len)
204 if ((count % 16) == 0)
206 if (count)
208 if (!fetch_line())
210 free(data);
211 return NULL;
215 ptr = strchr(line, ':');
216 if (!ptr)
218 free(data);
219 return NULL;
222 ptr += 2;
225 data[count++] = strtoul(ptr, NULL, 16);
226 ptr += 3;
229 return data;
232 void parse_urb_body(struct urb* urb)
234 int setup_packet = 0;
236 while (fetch_line())
238 if (line[0] == '[')
239 break;
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"))
271 setup_packet = 1;
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;
296 else
298 urb->func = FUNC_UNKNOWN;
299 printf("Unknown FUNC: %s\n", line);
300 exit(0);
306 void free_urb(struct urb* urb)
308 free(urb->data);
311 void print_urb(struct urb* urb)
313 unsigned int x;
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);
319 if( urb->data )
321 printf(" [");
322 for(x=0; x<urb->len; x++)
324 printf( "%02x", urb->data[x] );
325 if (x < urb->len-1)
326 printf(" ");
328 printf("]");
331 printf("\n");
334 struct rpt* find_report_by_seq(int seq)
336 struct rpt* rpt = rpts;
338 while( rpt )
340 if (rpt->seq == seq)
341 break;
343 rpt = rpt->next;
346 return rpt;
349 struct rpt* find_report_by_id(unsigned char id)
351 struct rpt* rpt = rpts;
353 while( rpt )
355 if (rpt->id == id)
356 break;
358 rpt = rpt->next;
361 return rpt;
364 void del_report(struct urb* urb)
366 unsigned char id = urb->data[0];
367 struct rpt* rpt = rpts;
368 struct rpt** prev = &rpts;
370 while( rpt )
372 if (rpt->id == id)
373 break;
375 prev = &(rpt->next);
376 rpt = rpt->next;
379 if (rpt)
381 *prev = rpt->next;
382 free(rpt);
386 void add_report(struct urb* urb)
388 struct rpt* rpt;
389 unsigned char id;
391 if (urb->data)
392 id = urb->data[0];
393 else
394 id = urb->value & 0xff;
396 if ((rpt = find_report_by_id(id)))
398 rpt->seq = urb->seq;
399 rpt->value = urb->value;
400 return;
403 rpt = (struct rpt*)malloc(sizeof(*rpt));
404 memset(rpt, 0, sizeof(*rpt));
406 rpt->id = id;
407 rpt->seq = urb->seq;
408 rpt->value = urb->value;
410 rpt->next = rpts;
411 rpts = rpt;
414 int check_and_update_report(struct urb* urb)
416 struct rpt* rpt;
418 rpt = find_report_by_seq(urb->seq);
419 if (!rpt)
420 return 0;
422 if (rpt->data && !memcmp(rpt->data, urb->data+1, urb->len-1))
423 return 0;
425 free(rpt->data);
426 rpt->len = urb->len-1;
427 rpt->data = (unsigned char *)malloc(rpt->len);
428 memcpy(rpt->data, urb->data+1, rpt->len);
430 return 1;
433 void display_report(struct urb* urb)
435 unsigned long data = 0;
436 char buf[9];
437 unsigned int n;
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]);
443 switch (urb->len)
445 case 5:
446 data = (data << 8) | urb->data[4];
447 case 4:
448 data = (data << 8) | urb->data[3];
449 case 3:
450 data = (data << 8) | urb->data[2];
451 case 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 );
455 break;
457 default:
458 n += printf( "-------- (----------)" );
459 break;
462 printf( "%*c", 55-n, ' ');
463 for (n=0; n<urb->len-1; n++)
464 printf("%02x ", urb->data[n+1]);
465 printf("\n");
466 fflush(stdout);
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)
475 return;
477 if (urb->request == REQ_GET_REPORT)
479 add_report(urb);
481 else if (urb->request == REQ_SET_REPORT)
483 display_report(urb);
484 del_report(urb);
487 else
489 if (urb->func == FUNC_CONTROL_TXFER)
491 if (check_and_update_report(urb))
492 display_report(urb);
494 else if (urb->data && urb->func == FUNC_BULK_TXFER)
496 add_report(urb);
497 if (check_and_update_report(urb))
498 display_report(urb);
503 int main(int argc, char* argv[])
505 struct urb urb;
507 file = stdin;
509 while(init_urb(&urb))
511 parse_urb_body(&urb);
513 update_reports(&urb);
515 free_urb(&urb);
518 return 0;