/release/src/router/apcupsd/examples/snoopdecode.c
C | 519 lines | 373 code | 73 blank | 73 comment | 91 complexity | d3fb928ede5634598e6eecd4cc4774c1 MD5 | raw file
- /*
- * snoopdecode.c
- *
- * Decodes traces captured by 'usbsnoop'
- * (http://benoit.papillault.free.fr/usbsnoop/index.php)
- *
- * See usbsnoop.txt for details.
- */
-
- /*
- * Copyright (C) 2004-2005 Adam Kropelin
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General
- * Public License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
-
- #define MAX_LINE 1024
-
- char line[MAX_LINE] = "";
- FILE* file;
-
- enum
- {
- DIR_UNKNOWN = 0,
- DIR_TO_DEVICE,
- DIR_FROM_DEVICE
- };
-
- enum
- {
- FUNC_UNKNOWN = 0,
- FUNC_CONTROL_TXFER,
- FUNC_CLASS_INTERFACE,
- FUNC_GET_DESC,
- FUNC_SELECT_CONFIG,
- FUNC_GET_DESC_FROM_IFACE,
- FUNC_BULK_TXFER,
- FUNC_RESET_PIPE,
- FUNC_ABORT_PIPE,
- };
-
- enum
- {
- REQ_GET_REPORT = 1,
- REQ_GET_IDLE = 2,
- REQ_GET_PROTOCOL = 3,
- REQ_SET_REPORT = 9,
- REQ_SET_IDLE = 10,
- REQ_SET_PROTOCOL = 11
- };
-
- struct urb
- {
- int seq;
- unsigned long len;
- unsigned char* data;
- unsigned long flags;
- unsigned long index;
- unsigned long type;
- unsigned long reserved;
- unsigned long request;
- unsigned long value;
- int time;
- int dir;
- int func;
- };
-
- struct rpt
- {
- struct rpt* next;
- unsigned char* data;
- int seq;
- unsigned short len;
- unsigned char id;
- unsigned long value;
- };
-
- struct rpt* rpts = NULL;
-
- /*
- [197 ms] >>> URB 1 going down >>>
- -- URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
- TransferBufferLength = 00000012
- TransferBuffer = 864c9208
- TransferBufferMDL = 00000000
- Index = 00000000
- DescriptorType = 00000001 (USB_DEVICE_DESCRIPTOR_TYPE)
- LanguageId = 00000000
- [203 ms] UsbSnoop - MyInternalIOCTLCompletion(f7b91db0) : fido=00000000, Irp=863df850, Context=86405d10, IRQL=2
-
- [203 ms] <<< URB 1 coming back <<<
- -- URB_FUNCTION_CONTROL_TRANSFER:
- PipeHandle = 863e4150
- TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
- TransferBufferLength = 00000012
- TransferBuffer = 864c9208
- TransferBufferMDL = 8640f108
- 00000000: 12 01 10 01 00 00 00 08 1d 05 02 00 06 00 03 01
- 00000010: 02 01
- UrbLink = 00000000
- */
-
- /*
- [59563 ms] >>> URB 346 going down >>>
- -- URB_FUNCTION_CLASS_INTERFACE:
- TransferFlags = 00000001 (USBD_TRANSFER_DIRECTION_IN, ~USBD_SHORT_TRANSFER_OK)
- TransferBufferLength = 00000005
- TransferBuffer = f7f12ba0
- TransferBufferMDL = 00000000
- UrbLink = 00000000
- RequestTypeReservedBits = 00000022
- Request = 00000001
- Value = 0000032f
- Index = 00000000
- [59567 ms] UsbSnoop - MyInternalIOCTLCompletion(f7b91db0) : fido=86397288, Irp=85ff4b40, Context=85f4b3d8, IRQL=2
- [59567 ms] <<< URB 346 coming back <<<
- -- URB_FUNCTION_CONTROL_TRANSFER:
- PipeHandle = 863e4150
- TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
- TransferBufferLength = 00000002
- TransferBuffer = f7f12ba0
- TransferBufferMDL = 85f102f0
- 00000000: 2f 02
- UrbLink = 00000000
- SetupPacket =
- 00000000: a1 01 2f 03 00 00 05 00
- */
-
- int fetch_line()
- {
- return !!fgets(line, sizeof(line), file);
- }
-
- int find_urb()
- {
- do
- {
- if (line[0] == '[' && strstr(line, " URB ") &&
- (strstr(line, "going down") || strstr(line, "coming back")))
- {
- return 1;
- }
- }
- while( fetch_line() );
-
- return 0;
- }
-
- int init_urb(struct urb* urb)
- {
- memset(urb, 0, sizeof(*urb));
-
- if (!find_urb())
- return 0;
-
- urb->time = atoi(line+1);
-
- if (strstr(line, "going down"))
- urb->dir = DIR_TO_DEVICE;
- else if(strstr(line, "coming back"))
- urb->dir = DIR_FROM_DEVICE;
- else
- urb->dir = DIR_UNKNOWN;
-
- urb->seq = atoi(strstr(line,"URB ")+4);
-
- return 1;
- }
-
- unsigned long get_hex_value()
- {
- char* ptr = strchr(line, '=');
- if (!ptr)
- return 0xffff;
-
- return strtoul(ptr+2, NULL, 16);
- }
-
- unsigned char* parse_data_dump(int len)
- {
- int count = 0;
- char* ptr= NULL;
-
- unsigned char* data = (unsigned char *)malloc(len);
- if (!data)
- return NULL;
-
- while(count < len)
- {
- if ((count % 16) == 0)
- {
- if (count)
- {
- if (!fetch_line())
- {
- free(data);
- return NULL;
- }
- }
-
- ptr = strchr(line, ':');
- if (!ptr)
- {
- free(data);
- return NULL;
- }
-
- ptr += 2;
- }
-
- data[count++] = strtoul(ptr, NULL, 16);
- ptr += 3;
- }
-
- return data;
- }
-
- void parse_urb_body(struct urb* urb)
- {
- int setup_packet = 0;
-
- while (fetch_line())
- {
- if (line[0] == '[')
- break;
-
- if (strstr(line, "TransferBufferLength"))
- {
- urb->len = get_hex_value();
- }
- else if (strstr(line, "TransferFlags"))
- {
- urb->flags = get_hex_value();
- }
- else if (strstr(line, "Index"))
- {
- urb->index = get_hex_value();
- }
- else if (strstr(line, "DescriptorType"))
- {
- urb->type = get_hex_value();
- }
- else if (strstr(line, "RequestTypeReservedBits"))
- {
- urb->reserved = get_hex_value();
- }
- else if (strstr(line, "Request"))
- {
- urb->request = get_hex_value();
- }
- else if (strstr(line, "Value"))
- {
- urb->value = get_hex_value();
- }
- else if (strstr(line, "SetupPacket"))
- {
- setup_packet = 1;
- }
- else if (strstr(line, "00000000:"))
- {
- if (!setup_packet && !urb->data)
- urb->data = parse_data_dump(urb->len);
- }
- else if (strstr(line, "-- URB_FUNCTION_"))
- {
- if (strstr(line, "URB_FUNCTION_CONTROL_TRANSFER"))
- urb->func = FUNC_CONTROL_TXFER;
- else if (strstr(line, "URB_FUNCTION_CLASS_INTERFACE"))
- urb->func = FUNC_CLASS_INTERFACE;
- else if (strstr(line, "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"))
- urb->func = FUNC_GET_DESC;
- else if (strstr(line, "URB_FUNCTION_SELECT_CONFIGURATION"))
- urb->func = FUNC_SELECT_CONFIG;
- else if (strstr(line, "URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"))
- urb->func = FUNC_GET_DESC_FROM_IFACE;
- else if (strstr(line, "URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"))
- urb->func = FUNC_BULK_TXFER;
- else if (strstr(line, "URB_FUNCTION_RESET_PIPE"))
- urb->func = FUNC_RESET_PIPE;
- else if (strstr(line, "URB_FUNCTION_ABORT_PIPE"))
- urb->func = FUNC_ABORT_PIPE;
- else
- {
- urb->func = FUNC_UNKNOWN;
- printf("Unknown FUNC: %s\n", line);
- exit(0);
- }
- }
- }
- }
-
- void free_urb(struct urb* urb)
- {
- free(urb->data);
- }
-
- void print_urb(struct urb* urb)
- {
- unsigned int x;
- printf("[%08d ms] %05d %c ", urb->time, urb->seq,
- (urb->dir == DIR_TO_DEVICE) ? '>' : (urb->dir == DIR_FROM_DEVICE) ? '<' : '?');
-
- printf("req=%04lx value=%04lx", urb->request, urb->value);
-
- if( urb->data )
- {
- printf(" [");
- for(x=0; x<urb->len; x++)
- {
- printf( "%02x", urb->data[x] );
- if (x < urb->len-1)
- printf(" ");
- }
- printf("]");
- }
-
- printf("\n");
- }
-
- struct rpt* find_report_by_seq(int seq)
- {
- struct rpt* rpt = rpts;
-
- while( rpt )
- {
- if (rpt->seq == seq)
- break;
-
- rpt = rpt->next;
- }
-
- return rpt;
- }
-
- struct rpt* find_report_by_id(unsigned char id)
- {
- struct rpt* rpt = rpts;
-
- while( rpt )
- {
- if (rpt->id == id)
- break;
-
- rpt = rpt->next;
- }
-
- return rpt;
- }
-
- void del_report(struct urb* urb)
- {
- unsigned char id = urb->data[0];
- struct rpt* rpt = rpts;
- struct rpt** prev = &rpts;
-
- while( rpt )
- {
- if (rpt->id == id)
- break;
-
- prev = &(rpt->next);
- rpt = rpt->next;
- }
-
- if (rpt)
- {
- *prev = rpt->next;
- free(rpt);
- }
- }
-
- void add_report(struct urb* urb)
- {
- struct rpt* rpt;
- unsigned char id;
-
- if (urb->data)
- id = urb->data[0];
- else
- id = urb->value & 0xff;
-
- if ((rpt = find_report_by_id(id)))
- {
- rpt->seq = urb->seq;
- rpt->value = urb->value;
- return;
- }
-
- rpt = (struct rpt*)malloc(sizeof(*rpt));
- memset(rpt, 0, sizeof(*rpt));
-
- rpt->id = id;
- rpt->seq = urb->seq;
- rpt->value = urb->value;
-
- rpt->next = rpts;
- rpts = rpt;
- }
-
- int check_and_update_report(struct urb* urb)
- {
- struct rpt* rpt;
-
- rpt = find_report_by_seq(urb->seq);
- if (!rpt)
- return 0;
-
- if (rpt->data && !memcmp(rpt->data, urb->data+1, urb->len-1))
- return 0;
-
- free(rpt->data);
- rpt->len = urb->len-1;
- rpt->data = (unsigned char *)malloc(rpt->len);
- memcpy(rpt->data, urb->data+1, rpt->len);
-
- return 1;
- }
-
- void display_report(struct urb* urb)
- {
- unsigned long data = 0;
- char buf[9];
- unsigned int n;
-
- n = printf( "[%04d s] %05d %c %s 0x%02x (%03u) ",
- urb->time/1000, urb->seq, urb->func == FUNC_BULK_TXFER ? '*' : ' ',
- urb->dir==DIR_TO_DEVICE ? "WRITE" : " READ", urb->data[0], urb->data[0]);
-
- switch (urb->len)
- {
- case 5:
- data = (data << 8) | urb->data[4];
- case 4:
- data = (data << 8) | urb->data[3];
- case 3:
- data = (data << 8) | urb->data[2];
- case 2:
- data = (data << 8) | urb->data[1];
- sprintf(buf, "%0*lx", (int)(urb->len-1)*2, data);
- n += printf( "%8s (%lu)", buf, data );
- break;
-
- default:
- n += printf( "-------- (----------)" );
- break;
- }
-
- printf( "%*c", 55-n, ' ');
- for (n=0; n<urb->len-1; n++)
- printf("%02x ", urb->data[n+1]);
- printf("\n");
- fflush(stdout);
- }
-
- void update_reports(struct urb* urb)
- {
- if (urb->dir == DIR_TO_DEVICE)
- {
- // Only care about class requests
- if (urb->func != FUNC_CLASS_INTERFACE)
- return;
-
- if (urb->request == REQ_GET_REPORT)
- {
- add_report(urb);
- }
- else if (urb->request == REQ_SET_REPORT)
- {
- display_report(urb);
- del_report(urb);
- }
- }
- else
- {
- if (urb->func == FUNC_CONTROL_TXFER)
- {
- if (check_and_update_report(urb))
- display_report(urb);
- }
- else if (urb->data && urb->func == FUNC_BULK_TXFER)
- {
- add_report(urb);
- if (check_and_update_report(urb))
- display_report(urb);
- }
- }
- }
-
- int main(int argc, char* argv[])
- {
- struct urb urb;
-
- file = stdin;
-
- while(init_urb(&urb))
- {
- parse_urb_body(&urb);
-
- update_reports(&urb);
-
- free_urb(&urb);
- }
-
- return 0;
- }