parse_sn9c201.pl: Add a parser for sn9c201 USB dumps
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 7 Dec 2010 14:30:27 +0000 (12:30 -0200)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 7 Dec 2010 14:30:27 +0000 (12:30 -0200)
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
contrib/sn9c201/parse_sn9c201.pl [new file with mode: 0755]

diff --git a/contrib/sn9c201/parse_sn9c201.pl b/contrib/sn9c201/parse_sn9c201.pl
new file mode 100755 (executable)
index 0000000..b402433
--- /dev/null
@@ -0,0 +1,139 @@
+#!/usr/bin/perl
+use strict;
+
+#   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, version 2 of the License.
+#
+#   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.
+#
+# This small script parses USB dumps generated by several drivers,
+# decoding USB bits.
+#
+# To use it, do:
+# dmesg | ./parse_usb.pl
+#
+# Also, there are other utilities that produce similar outputs, and it
+# is not hard to parse some USB analyzers log into the expected format.
+#
+
+sub i2c_reg($)
+{
+       my %decode;
+       my $reg = shift;
+
+       $reg =~ s/\s+.*//;
+       $reg = hex("$reg");
+
+       if ($reg & 0x01) {
+               $decode{"speed"} = "400kbps";
+       } else {
+               $decode{"speed"} = "100kbps";
+       }
+       if ($reg & 0x02) {
+               $decode{"op"} = "RD";
+       } else {
+               $decode{"op"} = "WR";
+       }
+       $decode{"busy"} = "BUSY" if (($reg & 0x04) == 0);
+       $decode{"err"} = "ERR" if ($reg & 0x08);
+       $decode{"size"} = ($reg >> 4) & 7;
+       $decode{"i2c"} = "3wire" if (($reg & 0x80) == 0);
+
+       return %decode;
+}
+
+sub type_req($)
+{
+       my $reqtype = shift;
+       my $s;
+
+       if ($reqtype & 0x80) {
+               $s = "RD ";
+       } else {
+               $s = "WR ";
+       }
+       if (($reqtype & 0x60) == 0x20) {
+               $s .= "CLAS ";
+       } elsif (($reqtype & 0x60) == 0x40) {
+               $s .= "VEND ";
+       } elsif (($reqtype & 0x60) == 0x60) {
+               $s .= "RSVD ";
+       }
+
+       if (($reqtype & 0x1f) == 0x00) {
+               $s .= "DEV ";
+       } elsif (($reqtype & 0x1f) == 0x01) {
+               $s .= "INT ";
+       } elsif (($reqtype & 0x1f) == 0x02) {
+               $s .= "EP ";
+       } elsif (($reqtype & 0x1f) == 0x03) {
+               $s .= "OTHER ";
+       } elsif (($reqtype & 0x1f) == 0x04) {
+               $s .= "PORT ";
+       } elsif (($reqtype & 0x1f) == 0x05) {
+               $s .= "RPIPE ";
+       } else {
+               $s .= sprintf "RECIP 0x%02x ", $reqtype & 0x1f;
+       }
+
+       $s =~ s/\s+$//;
+       return $s;
+}
+
+my %i2c;
+my $i2c_id;
+while (<>) {
+       tr/A-F/a-f/;
+       if (m/([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].) ([0-9a-f].)[\<\>\s]+(.*)/) {
+               my $reqtype = hex($1);
+               my $req = hex($2);
+               my $wvalue = hex("$4$3");
+               my $windex = hex("$6$5");
+               my $wlen = hex("$8$7");
+               my $payload = $9;
+               my $fullpayload = $9;
+
+               %i2c = i2c_reg($payload) if ($wvalue == 0x10c0);
+
+               if (($wvalue >= 0x10c0) && ($wvalue <= 0x10c2)) {
+                       my $reg = $wvalue;
+                       if ($reg == 0x10c0) {
+                               $payload =~ s/^([0-9a-f].)//;
+                               $payload =~ s/^\s+//;
+                               $reg++;
+                       }
+                       if ($reg == 0x10c1 && $payload ne "") {
+                               $i2c_id = $payload;
+                               $i2c_id =~ s/\s+.*//;
+                               $i2c_id = "addr=0x$i2c_id, ";
+                               $payload =~ s/^([0-9a-f].)//;
+                               $payload =~ s/^\s+//;
+                               $reg++;
+                       }
+
+#                      my $data = $payload;
+#                      $payload =~ 
+
+                       my $s = sprintf "%s %s %s %s %s size=%d",
+                               $i2c{"op"}, $i2c{"speed"}, $i2c{"busy"}, $i2c{"err"}, $i2c{"i2c"}, $i2c{"size"};
+                       $s =~ s/\s+/ /g;
+
+                       if ($reqtype & 0x80) {
+                               printf "Read I2C: $s $i2c_id$payload\n";
+                       } else {
+                               printf "I2C $s $i2c_id$payload\n";
+                       }
+                       printf("\t%s, Req %3d, wValue: 0x%04x, wIndex 0x%04x, wlen %d: %s\n",
+                               type_req($reqtype), $req, $wvalue, $windex, $wlen, $fullpayload);
+               } else {
+                       printf("%s, Req %3d, wValue: 0x%04x, wIndex 0x%04x, wlen %d: %s\n",
+                               type_req($reqtype), $req, $wvalue, $windex, $wlen, $payload);
+               }
+       }
+}