#! /usr/bin/python

# This modules is used to parse trace files generated using usbsnoop. I'm assuming that
# the file is well formed hence no real format compliancy checking is done. This is barely my second
# python script... so don't blame my python incompetence :) and as usual:
# (C) Ilyes Gouta, 2006-2007.

import sys
import re
import string

def DecodeReadRequest(packet, value):
    l = re.split("\\s", packet);
    print "usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x%s, 0x%s, 0x%s, 0x%s%s, buff, 1, 100); // should be 0x%s" % (l[1], l[0], l[2], l[5], l[4], value);

def DecodeWriteRequest(packet, value, size):
    l = re.split("\\s", packet);
    m = re.split("\\s", value);

    print "{"
    print "    unsigned char buffer[%i] = {" % size,
    for x in range(size):
        print "0x%s," % m[x],
    print "};";
    print "    memcpy(kbuff, buffer, sizeof(buffer)); /* kbuff == cam->control_buffer */"
    print "    usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x%s, 0x%s, 0x%s, 0x%s%s, kbuff, %i, 100);" % (l[1], l[0], l[2], l[5], l[4], size);
    print "}";

def HandleInputURB(f):
    line = f.readline();
    i = line.find("=");
    buffersize = line[i + 1:]; # Get the buffer size of the transmitted URB.
                               # This is usefull to detect the firmware upload sequence.
    while line.find("00000000:") == -1:
        line = f.readline();

    i = line.find(":");
    value = line[i + 1:];

    while line.find("SetupPacket") == -1:
    	line = f.readline();

    line = f.readline();
    i = line.find(":");
    SetupPacket = line[i + 1:];

    DecodeReadRequest(SetupPacket[1:-1], value[1:-1]);

def HandleOutputURB(f):
    line = f.readline();
    i = line.find("=");
    buffersize = line[i + 1:]; # Get the buffer size of the transmitted URB.
                               # This is usefull to detect the firmware upload sequence.
    f.readline();
    f.readline();

    line = f.readline(); # Get the TransferBufferMDL
    value = "";

    while line.find(":") != -1:
        i = line.find(":");
        value = value + line[i + 1:-1];
        line = f.readline();

    while line.find("SetupPacket") == -1:
    	line = f.readline();

    line = f.readline();
    i = line.find(":");
    SetupPacket = line[i + 1:];

    DecodeWriteRequest(SetupPacket[1:-1], value[1:], int(buffersize[1:-1], 16));

# Only three URB types are handled: URB_FUNCTION_VENDOR_DEVICE, URB_FUNCTION_ISOCH_TRANSFER and URB_FUNCTION_SELECT_INTERFACE.
def AnalyzeURB(f):
    f.readline();
    line = f.readline();

    if line.find("UsbSnoop - incorrect") != -1:
        f.readline();
        f.readline();
        line = f.readline();
        if line.find("URB_FUNCTION_SELECT_INTERFACE") != -1:
            print ">>> URB_FUNCTION_SELECT_INTERFACE";
            return;

    if line.find("URB_FUNCTION_VENDOR_DEVICE") != -1: # This will handle the most configuration URBs.
        line = f.readline();
        if line.find("USBD_TRANSFER_DIRECTION_IN") != -1:
            HandleInputURB(f);
        else:
            HandleOutputURB(f);
        return;

    if line.find("URB_FUNCTION_ISOCH_TRANSFER") != -1: # This will handle isochronous URBs.
        print "/* >>> URB_FUNCTION_ISOCH_TRANSFER */";
        return;

    if line.find("URB_FUNCTION_RESET_PIPE") != -1:
        print "/* >>> URB_FUNCTION_RESET_PIPE */";
        return;

    if line.find("URB_FUNCTION_GET_CURRENT_FRAME_NUMBER") != -1:
        print "/* >>> URB_FUNCTION_GET_CURRENT_FRAME_NUMBER */";
        return;

    if line.find("URB_FUNCTION_SELECT_INTERFACE") != -1:
        print "/* >>> URB_FUNCTION_SELECT_INTERFACE */";
        return;

def ParseFile(fn):
    print "Parsing: %s ..." % (fn);
    f = open(fn , "r");
    line = f.readline();
    while line:
        if line.find("UsbSnoop - MyDispatchInternalIOCTL") != -1:
            AnalyzeURB(f);
        line = f.readline();

# Main entry point: call the parse function.
if len(sys.argv) != 2:
    print "Usage: ./parse.py <usbsnoop trace file>"
else:
    ParseFile(sys.argv[1]);
