ULi M920x parse
Jump to navigation
Jump to search
This ULi M920x specific script processes usbsnoop log files (as well as those which have been parsed by mrec's parser.pl utility).
#!/usr/bin/perl use Getopt::Std; sub expand_string { my @arr = (); my ($str) = @_; if (length($str) == 8) { push(@arr, substr($str, 0, 2)); push(@arr, substr($str, 2, 2)); push(@arr, substr($str, 4, 2)); push(@arr, substr($str, 6, 2)); }elsif(length($str) == 4) { push(@arr, substr($str, 0, 2)); push(@arr, substr($str, 2, 2)); }elsif(length($str) == 2) { push(@arr, $str); }elsif(length($str) == 1) { return; } return @arr; } sub expand_string_long { my @bytes = (); my (@str) = @_; foreach(@str) { #@arr = expand_string($_); #foreach(@arr){ # push(@bytes, $_); #} @bytes = ( @bytes, expand_string($_) ); } return @bytes; } sub print_array_bytes { my (@str) = @_; foreach(expand_string_long(@str)){ print "$_ "; } } sub print_bytes { my ($str) = @_; print_array_bytes(split(/ /, $str)); } sub check { my ($cmd, @bytes) = @_; my @cmp; my $i; #print "cmd <$cmd>\n"; my $fail = 0; @cmp = split(/ /, $cmd); for ($i = 0; $i < scalar(@cmp); $i++) { #print "check $bytes[$i] vs $cmp[$i]\n"; if ($cmp[$i] == "-1") { next; } if (not($bytes[$i] =~ m/$cmp[$i]/)) { $fail = 1; print "($bytes[$i]!=$cmp[$i], $i)"; } } if ($fail) { print "\n"; print_array_bytes(@bytes); print "\n$cmd\n"; } } sub get_line { my ($cmd) = @_; # xxx: could be more flexible my @ret; my @cmp; my $i; again: while($line = <STDIN>) { #001295: OUT: 000002 ms 135775 ms 40 23 c0 00 80 00 00 00 >>> if($input eq "us" && $line =~ m/\S+: \S+: \S+ ms \S+ ms ([a-fA-F0-9 ]+)/) { @ret = split(/ /, $1); $foo = $1; @ret[2,3,4,5,6,7] = @ret[3,2,5,4,7,6]; last; } if($input eq "um" && $line =~ m/\S+ \S+ \S+ \S+ s ([a-fA-F0-9 ]+)/) { @ret = expand_string_long(split(/ /, $1)); $foo = $1; last; } } @cmp = split(/ /, $cmd); for ($i = 0; $i < scalar(@cmp); $i++) { if ($cmp[$i] == "-1") { next; } if (not($cmp[$i] eq $ret[$i])) { #print "fail\n"; goto again; } } return @ret; } sub us_get_write { #print "<$line>\n"; if($input == "us" && $line =~ m/>>>\s+([a-fA-F0-9 ]+)/) { return split(/ /, $1); } if($input == "um") { if($line =~ m/\S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ \S+ = ([a-fA-F0-9 ]+)/) { #print "read match $line\n"; return expand_string_long(split(/ /, $1)); } } } sub get_read { #print "<$line>\n"; if($input == "us" && $line =~ m/<<< ([a-fA-F0-9 ]+)/) { return split(/ /, $1); } if($input == "um") { while($line = <STDIN>) { if($line =~ m/\S+ \S+ \S+ \S+ \S+ \S+ = ([a-fA-F0-9 ]+)/) { return expand_string_long(split(/ /, $1)); } } } } sub usage { print STDERR << "EOF"; -i um (usbmon) us (usb snoop) sp (snoopy pro) -m fw (extract firmware) i2c (show i2c traffic) EOF exit; } getopts("m:i:", \%opt ) or usage(); $mode = $opt{m}; $input = $opt{i}; if ($input != "um" && $input != "us" && $input != "sp") { usage(); } if ($mode != "fw" && $mode != "i2c") { usage(); } if ($mode eq "fw") { open(out, ">fw") || die "Can't open fw"; while(@bytes = get_line()) { if(scalar(@bytes) <= 1) { last; } $len = hex($bytes[6] . $bytes[7]); if ($len < 32) { next; } @fw_bytes = us_get_write(); if ($len != scalar(@fw_bytes)) { #note: usbmon will not log bulk writes longer than 32 bytes by default print "bulk size doesn't match! Check usbmon.\n"; print $len . " != " . scalar(@fw_bytes) . "\n"; exit(0); } print out pack("v", hex($bytes[2] . $bytes[3])); print out pack("v", hex($bytes[4] . $bytes[5])); print out pack("v", scalar(@fw_bytes)); foreach(@fw_bytes) { print out pack("C", hex($_)); } } exit(1); } while(@bytes = get_line("-1")) { if(scalar(@bytes) <= 1) { last; } $master_line = $. - 1; if ($bytes[0] == "40" && $bytes[1] == "23") { if ($bytes[4] == "80" || $bytes[4] == "00") { my $multibyte = 0; my $addr; $addr = $bytes[2]; printf "%06d: ", $master_line; print "addr $addr "; if (hex($addr) & 0x1) { print "Invalid address\n"; } @bytes = get_line("40 23"); $reg = $bytes[2]; if ($bytes[4] == "80") { $multibyte = 1; } else { @bytes = get_line("40 23"); } #if ($bytes[4] != "40") { # print "(missing 40)"; #} if ($bytes[4] == "80") { if ($multibyte == 0) { $raddr = sprintf("%02x", hex($addr) | 0x1); check("40 23 $raddr 00 80 00 00 00", @bytes); @bytes = get_line("c0 23"); print "reg $reg = "; } else { print "$reg = "; @bytes = get_line("c0 23"); while ($bytes[4] == "21") { check("c0 23 00 00 21 00 -1 -1", @bytes); @bytes = get_read(); print_array_bytes(@bytes); @bytes = get_line("c0 23"); } } check("c0 23 -1 00 60 00 -1 -1", @bytes); @bytes = get_read(); print_array_bytes(@bytes); print "read\n"; } else { check("40 23 -1 00 4|00 00 00 00", @bytes); print "reg $reg = $bytes[2]"; while ($bytes[4] != "40") { @bytes = get_line("40 23"); check("40 23 -1 00 4|00 00 00 00", @bytes); print " $bytes[2]"; } print "\n"; } } } }