parse_au0828.pl: Add a parser to help with au0828 debug
authorMauro Carvalho Chehab <m.chehab@samsung.com>
Sat, 26 Jul 2014 01:42:42 +0000 (22:42 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Sat, 26 Jul 2014 01:49:04 +0000 (22:49 -0300)
This parser is not 100%, but it properly handles the I2C
registers, making easier to understand the parsed logic.

Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
contrib/au0828/parse_au0828.pl [new file with mode: 0755]

diff --git a/contrib/au0828/parse_au0828.pl b/contrib/au0828/parse_au0828.pl
new file mode 100755 (executable)
index 0000000..37a127b
--- /dev/null
@@ -0,0 +1,154 @@
+#!/usr/bin/perl
+use strict;
+
+#   Copyright (C) 2014 Mauro Carvalho Chehab <m.chehab@samsung.com>
+#   Copyright (c) 2014 Samsung Electronics Co., Ltd.
+#
+#   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.
+#
+
+my %speed_map = (
+       0x07 => "250KHz",
+       0x14 => "100KHz",
+       0x40 => "30KHz",
+       0x60 => "20KHz",
+);
+
+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_speed = "unknown";
+my $i2c_addr = "unknown";
+my @i2c_sbuf;
+my @i2c_rbuf;
+my $i2c_hold;
+
+while (<>) {
+       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 $timestamp = $1;
+               my $reqtype = hex($2);
+               my $req = hex($3);
+               my $val = hex("$5$4");
+               my $reg = hex("$7$6");
+               my $wlen = hex("$9$8");
+               my $payload = $10;
+
+               $timestamp =~ s/^\s+//;
+               $timestamp =~ s/\s+$//;
+
+               if (($reqtype == 0x40) && ($reg == 0x02ff)) {
+                       # Start of an I2C tranfer
+                       @i2c_sbuf = ();
+                       @i2c_rbuf = ();
+                       next;
+               }
+               if (($reqtype == 0x40) && ($reg == 0x0202)) {
+                       # I2C speed
+                       $i2c_speed = sprintf "0x%02x", $val;
+                       $i2c_speed = $speed_map{$val} if defined($speed_map{$val});
+                       next;
+               }
+
+               if (($reqtype == 0x40) && ($reg == 0x0203)) {
+                       # I2C addr
+                       $i2c_addr = $val >> 1;
+                       next;
+               }
+
+               if (($reqtype == 0x40) && ($reg == 0x0200)) {
+                       # I2C trigger
+                       $i2c_hold = ($val & 0x40) == 0x40;
+
+                       if (!$i2c_hold && ($val & 0x01)) {
+                               printf "$timestamp au0828 I2C write addr = 0x%02x (speed = %s) ", $i2c_addr, $i2c_speed;
+                               printf "0x%02x ", $_ foreach (@i2c_sbuf);
+                               print "\n";
+
+                               @i2c_sbuf = ();
+                       }
+
+                       next;
+               }
+
+               if (($reqtype == 0xc0) && ($reg == 0x0201)) {
+                       # Wait to be ready
+                       next;
+               }
+
+
+               if (($reqtype == 0x40) && ($reg == 0x0205)) {
+                       # I2C write data
+                       push @i2c_sbuf, $val;
+
+                       next;
+               }
+
+               if (($reqtype == 0xc0) && ($reg == 0x0209)) {
+                       # I2C read data
+                       push @i2c_rbuf, $val;
+
+                       if (!$i2c_hold) {
+                               printf "$timestamp au0828 I2C read addr = 0x%02x (speed = %s) ", $i2c_addr, $i2c_speed;
+                               printf "0x%02x ", $_ foreach (@i2c_rbuf);
+                               print "\n";
+
+                               @i2c_rbuf = ();
+                       }
+                       next;
+               }
+
+               printf("%s %s(0x%02x), Req 0x%02x, register 0x%04x, value 0x%04x, wlen %d: %s\n",
+                       $timestamp, type_req($reqtype), $reqtype, $req, $reg, $val, $wlen, $payload);
+       }
+}