root/i2c-tools/trunk/stub/i2c-stub-from-dump @ 5280

Revision 5280, 3.9 KB (checked in by khali, 6 years ago)

Add support for partial dumps.
Report if only garbage is found in dump file.

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl -w
2#
3# Copyright (C) 2007-2008  Jean Delvare <khali@linux-fr.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18# MA  02110-1301, USA
19#
20# This script feeds the i2c-stub driver with dump data from a real
21# I2C or SMBus chip. This can be useful when writing a driver for
22# a device you do not have access to, but of which you have a dump.
23
24use strict;
25use vars qw($bus_nr $addr $bytes $words);
26
27# Kernel version detection code by Mark M. Hoffman,
28# copied from sensors-detect.
29use vars qw(@kernel_version);
30
31sub initialize_kernel_version
32{
33        `uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
34        @kernel_version = ($1, $2, $3, $4);
35}
36
37sub kernel_version_at_least
38{
39        my ($vers, $plvl, $slvl) = @_;
40        return 1 if ($kernel_version[0]  > $vers ||
41                      ($kernel_version[0] == $vers && 
42                        ($kernel_version[1]  > $plvl || 
43                          ($kernel_version[1] == $plvl && 
44                            ($kernel_version[2] >= $slvl)))));
45        return 0;
46}
47
48# Find out the i2c bus number of i2c-stub
49sub get_i2c_stub_bus_number
50{
51        my $nr;
52
53        open(FH, "i2cdetect -l |") || die "Can't run i2cdetect";
54        while (<FH>) {
55                next unless m/^i2c-(\d+).*\tSMBus stub/;
56                $nr = $1;
57                last;
58        }
59        close(FH);
60
61        if (!defined($nr)) {
62                print STDERR "Please load i2c-stub first\n";
63                exit 2;
64        }
65
66        return $nr;
67}
68
69sub process_dump
70{
71        my $dump = shift;
72
73        open(DUMP, $dump) || die "Can't open $dump: $!\n";
74 OUTER_LOOP:
75        while (<DUMP>) {
76                if (m/^([0-9a-f]0):(( [0-9a-fX]{2}){16})/) {
77                        # Byte dump
78                        my $offset = hex($1);
79                        my @values = split(/ /, $2);
80                        shift(@values);
81                        for (my $i = 0; $i < 16 && (my $val = shift(@values)); $i++) {
82                                next if $val =~ m/X/;
83                                last OUTER_LOOP if system("i2cset", "-y",
84                                        $bus_nr, $addr,
85                                        sprintf("0x\%02x", $offset+$i),
86                                        "0x$val", "b");
87                                $bytes++;
88                        }
89                } elsif (m/^([0-9a-f][08]):(( [0-9a-fX]{4}){8})/) {
90                        # Word dump
91                        my $offset = hex($1);
92                        my @values = split(/ /, $2);
93                        shift(@values);
94                        for (my $i = 0; $i < 8 && (my $val = shift(@values)); $i++) {
95                                next if $val =~ m/X/;
96                                last OUTER_LOOP if system("i2cset", "-y",
97                                        $bus_nr, $addr,
98                                        sprintf("0x\%02x", $offset+$i),
99                                        "0x$val", "w");
100                                $words++;
101                        }
102                }
103        }
104        close(DUMP);
105}
106
107if ($>) {
108        print "You must be root to use this script\n";
109        exit 1;
110}
111
112if (@ARGV != 2) {
113        print STDERR "Usage: i2c-stub-from-dump <addr> <dump file>\n";
114        exit 1;
115}
116
117# Check the parameters
118$addr = $ARGV[0];
119if ($addr !~ m/^0x[0-7][0-9a-f]$/i) {
120        print STDERR "Invalid address $addr\n";
121        exit 1;
122}
123
124initialize_kernel_version();
125
126# Load the required kernel drivers if needed
127system("/sbin/modprobe", "i2c-dev") == 0 || exit 1;
128if (kernel_version_at_least(2, 6, 19)) {
129        system("/sbin/modprobe", "i2c-stub", "chip_addr=$addr") == 0 || exit 1;
130} else {
131        system("/sbin/modprobe", "i2c-stub") == 0 || exit 1;
132}
133sleep(1); # udev may take some time to create the device node
134
135$bus_nr = get_i2c_stub_bus_number();
136$bytes = $words = 0;
137
138# We don't want to see the output of 256 i2cset
139open(SAVEOUT, ">&STDOUT");
140open(STDOUT, ">/dev/null");
141process_dump($ARGV[1]);
142close(STDOUT);
143
144if ($bytes) {
145        printf SAVEOUT "$bytes byte values written to \%d-\%04x\n",
146                $bus_nr, oct($addr);
147}
148
149if ($words) {
150        printf SAVEOUT "$words word values written to \%d-\%04x\n",
151                $bus_nr, oct($addr);
152}
153
154if ($bytes + $words == 0) {
155        printf SAVEOUT "Only garbage found in dump file $ARGV[1]\n";
156        exit(1);
157}
158
159exit(0);
Note: See TracBrowser for help on using the browser.