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

Revision 5149, 3.8 KB (checked in by khali, 7 years ago)

Add support for word register access mode.

  • 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-f]{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                                last OUTER_LOOP if system("i2cset", "-y",
83                                        $bus_nr, $addr,
84                                        sprintf("0x\%02x", $offset+$i),
85                                        "0x$val", "b");
86                                $bytes++;
87                        }
88                } elsif (m/^([0-9a-f][08]):(( [0-9a-f]{4}){8})/) {
89                        # Word dump
90                        my $offset = hex($1);
91                        my @values = split(/ /, $2);
92                        shift(@values);
93                        for (my $i = 0; $i < 8 && (my $val = shift(@values)); $i++) {
94                                last OUTER_LOOP if system("i2cset", "-y",
95                                        $bus_nr, $addr,
96                                        sprintf("0x\%02x", $offset+$i),
97                                        "0x$val", "w");
98                                $words++;
99                        }
100                }
101        }
102        close(DUMP);
103}
104
105if ($>) {
106        print "You must be root to use this script\n";
107        exit 1;
108}
109
110if (@ARGV != 2) {
111        print STDERR "Usage: i2c-stub-from-dump <addr> <dump file>\n";
112        exit 1;
113}
114
115# Check the parameters
116$addr = $ARGV[0];
117if ($addr !~ m/^0x[0-7][0-9a-f]$/i) {
118        print STDERR "Invalid address $addr\n";
119        exit 1;
120}
121
122initialize_kernel_version();
123
124# Load the required kernel drivers if needed
125system("/sbin/modprobe", "i2c-dev") == 0 || exit 1;
126if (kernel_version_at_least(2, 6, 19)) {
127        system("/sbin/modprobe", "i2c-stub", "chip_addr=$addr") == 0 || exit 1;
128} else {
129        system("/sbin/modprobe", "i2c-stub") == 0 || exit 1;
130}
131sleep(1); # udev may take some time to create the device node
132
133$bus_nr = get_i2c_stub_bus_number();
134$bytes = $words = 0;
135
136# We don't want to see the output of 256 i2cset
137open(SAVEOUT, ">&STDOUT");
138open(STDOUT, ">/dev/null");
139process_dump($ARGV[1]);
140close(STDOUT);
141
142if ($bytes) {
143        printf SAVEOUT "$bytes byte values written to \%d-\%04x\n",
144                $bus_nr, oct($addr);
145}
146
147if ($words) {
148        printf SAVEOUT "$words word values written to \%d-\%04x\n",
149                $bus_nr, oct($addr);
150}
151
152exit($bytes + $words == 0);
Note: See TracBrowser for help on using the browser.