diff --git a/CHANGES b/CHANGES index baedcd5..fb1336b 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ i2c-tools CHANGES SVN i2cset: Final status messages go to stdout Return success even when readback fails or doesn't match + i2c-stub-from-dump: Helper script to use with i2c-stub 3.0.0 (2007-10-14) Initial release diff --git a/Makefile b/Makefile index 71119e7..a2bf718 100644 --- a/Makefile +++ b/Makefile @@ -33,4 +33,5 @@ all: include eeprom/Module.mk include include/Module.mk +include stub/Module.mk include tools/Module.mk diff --git a/README b/README index ee118f4..700bf88 100644 --- a/README +++ b/README @@ -27,6 +27,10 @@ category has its own sub-directory: * py-smbus Python wrapper for SMBus access over i2c-dev. Not installed by default. +* stub + A helper script to use with the i2c-stub kernel driver. Installed by + default. + * tools I2C device detection and register dump tools. These tools rely on the "i2c-dev" kernel driver. They are installed by default. diff --git a/stub/Module.mk b/stub/Module.mk new file mode 100644 index 0000000..144c90e --- /dev/null +++ b/stub/Module.mk @@ -0,0 +1,22 @@ +# Helper for the Linux i2c-stub bus driver +# +# Copyright (C) 2007 Jean Delvare +# +# Licensed under the GNU General Public License. + +STUB_DIR := stub + +# +# Commands +# + +install-stub: $(STUB_DIR)/i2c-stub-from-dump + $(INSTALL_DIR) $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) $(STUB_DIR)/i2c-stub-from-dump $(DESTDIR)$(bindir) + +uninstall-stub: + $(RM) $(DESTDIR)$(bindir)/i2c-stub-from-dump + +install: install-stub + +uninstall: uninstall-stub diff --git a/stub/i2c-stub-from-dump b/stub/i2c-stub-from-dump new file mode 100755 index 0000000..4c14faf --- /dev/null +++ b/stub/i2c-stub-from-dump @@ -0,0 +1,100 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2007 Jean Delvare +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA +# +# This script feeds the i2c-stub driver with dump data from a real +# I2C or SMBus chip. This can be useful when writing a driver for +# a device you do not have access to, but of which you have a dump. + +use strict; +use vars qw($bus_nr $addr $count); + +# Find out the i2c bus number of i2c-stub +sub get_i2c_stub_bus_number +{ + my $nr; + + open(FH, "i2cdetect -l |") || die "Can't run i2cdetect"; + while () { + next unless m/^i2c-(\d+).*\tSMBus stub/; + $nr = $1; + last; + } + close(FH); + + if (!defined($nr)) { + print STDERR "Please load i2c-stub first\n"; + exit 2; + } + + return $nr; +} + +if ($>) { + print "You must be root to use this script\n"; + exit 1; +} + +if (@ARGV != 2) { + print STDERR "Usage: i2c-stub-from-dump \n"; + exit 1; +} + +# Check the parameters +$addr = $ARGV[0]; +if ($addr !~ m/^0x[0-7][0-9a-f]$/i) { + print STDERR "Invalid address $addr\n"; + exit 1; +} + +# Load the required kernel drivers if needed +system("/sbin/modprobe", "i2c-dev") == 0 || exit 1; +system("/sbin/modprobe", "i2c-stub", "chip_addr=$addr") == 0 || exit 1; +sleep(1); # udev may take some time to create the device node + +$bus_nr = get_i2c_stub_bus_number(); + +# We don't want to see the output of 256 i2cset +open(SAVEOUT, ">&STDOUT"); +open(STDOUT, ">/dev/null"); + +$count = 0; +open(DUMP, $ARGV[1]) || die "Can't open $ARGV[1]: $!\n"; +OUTER_LOOP: +while () { + next unless m/^([0-9a-f]0):(( [0-9a-f]{2}){16})/; + my $offset = hex($1); + my @values = split(/ /, $2); + shift(@values); + for (my $i = 0; $i < 16 && (my $val = shift(@values)); $i++) { + last OUTER_LOOP if system("i2cset", "-y", + $bus_nr, $addr, + sprintf("0x\%02x", $offset+$i), + sprintf("0x\%02x", hex($val)), "b"); + $count++; + } +} +close(DUMP); +close(STDOUT); + +if ($count) { + printf SAVEOUT "$count byte values written to \%d-\%04x\n", + $bus_nr, oct($addr); +} + +exit($count == 0);