first commit

This commit is contained in:
pandacraft 2025-03-21 16:04:17 +01:00
commit a5a0434432
1126 changed files with 439481 additions and 0 deletions

View file

@ -0,0 +1,27 @@
# Helper for the Linux i2c-stub bus driver
#
# Copyright (C) 2007-2008 Jean Delvare <khali@linux-fr.org>
#
# 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.
STUB_DIR := stub
#
# Commands
#
install-stub: $(STUB_DIR)/i2c-stub-from-dump
$(INSTALL_DIR) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) $(STUB_DIR)/i2c-stub-from-dump $(DESTDIR)$(sbindir)
$(INSTALL_DATA) $(STUB_DIR)/i2c-stub-from-dump.8 $(DESTDIR)$(man8dir)
uninstall-stub:
$(RM) $(DESTDIR)$(sbindir)/i2c-stub-from-dump
$(RM) $(DESTDIR)$(man8dir)/i2c-stub-from-dump.8
install: install-stub
uninstall: uninstall-stub

View file

@ -0,0 +1,229 @@
#!/usr/bin/perl -w
#
# Copyright (C) 2007-2008 Jean Delvare <khali@linux-fr.org>
#
# 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 $err);
# Kernel version detection code by Mark M. Hoffman,
# copied from sensors-detect.
use vars qw(@kernel_version);
sub initialize_kernel_version
{
`uname -r` =~ /(\d+)\.(\d+)\.(\d+)(.*)/;
@kernel_version = ($1, $2, $3, $4);
}
sub kernel_version_at_least
{
my ($vers, $plvl, $slvl) = @_;
return 1 if ($kernel_version[0] > $vers ||
($kernel_version[0] == $vers &&
($kernel_version[1] > $plvl ||
($kernel_version[1] == $plvl &&
($kernel_version[2] >= $slvl)))));
return 0;
}
# 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 (<FH>) {
next unless m/^i2c-(\d+).*\tSMBus stub/;
$nr = $1;
last;
}
close(FH);
return $nr;
}
# Unload i2c-stub if we need an address it doesn't offer
sub check_chip_addr {
my $chip_addr_file = shift;
my @addr = @{shift()};
local $_;
open(CHIP_ADDR, $chip_addr_file) || return;
$_ = <CHIP_ADDR>;
chomp;
my %stub_addr = map { $_ => 1 } split ',';
close(CHIP_ADDR);
foreach my $addr (@addr) {
unless (exists $stub_addr{$addr}) {
print STDERR "Cycling i2c-stub to get the address we need\n";
system("/sbin/rmmod", "i2c-stub");
return;
}
}
}
# Load the required kernel drivers if needed
sub load_kernel_drivers
{
local $_;
my @addr = @{shift()};
my $nr;
# i2c-stub may be loaded without the address we want
check_chip_addr("/sys/module/i2c_stub/parameters/chip_addr", \@addr);
# Maybe everything is already loaded
$nr = get_i2c_stub_bus_number();
return $nr if defined $nr;
system("/sbin/modprobe", "i2c-dev") == 0 || exit 1;
if (kernel_version_at_least(2, 6, 19)) {
system("/sbin/modprobe", "i2c-stub",
"chip_addr=".join(',', @addr)) == 0 || exit 1;
} else {
system("/sbin/modprobe", "i2c-stub") == 0 || exit 1;
}
# udev may take some time to create the device node
if (!(-x "/sbin/udevadm" && system("/sbin/udevadm settle") == 0)
&& !(-x "/sbin/udevsettle" && system("/sbin/udevsettle") == 0)) {
sleep(1);
}
$nr = get_i2c_stub_bus_number();
if (!defined($nr)) {
print STDERR "Please load i2c-stub first\n";
exit 2;
}
return $nr;
}
sub process_dump
{
my ($addr, $dump) = @_;
my $err = 0;
my ($bytes, $words);
open(DUMP, $dump) || die "Can't open $dump: $!\n";
OUTER_LOOP:
while (<DUMP>) {
if (m/^([0-9a-f]0):(( [0-9a-fX]{2}){16})/) {
# Byte dump
my $offset = hex($1);
my @values = split(/ /, $2);
shift(@values);
for (my $i = 0; $i < 16 && (my $val = shift(@values)); $i++) {
next if $val =~ m/X/;
if (system("i2cset", "-y", $bus_nr, $addr,
sprintf("0x\%02x", $offset+$i),
"0x$val", "b")) {
$err = 3;
last OUTER_LOOP;
}
$bytes++;
}
} elsif (m/^([0-9a-f][08]):(( [0-9a-fX]{4}){8})/) {
# Word dump
my $offset = hex($1);
my @values = split(/ /, $2);
shift(@values);
for (my $i = 0; $i < 8 && (my $val = shift(@values)); $i++) {
next if $val =~ m/X/;
if (system("i2cset", "-y", $bus_nr, $addr,
sprintf("0x\%02x", $offset+$i),
"0x$val", "w")) {
$err = 3;
last OUTER_LOOP;
}
$words++;
}
}
}
close(DUMP);
if ($bytes) {
printf SAVEOUT "$bytes byte values written to \%d-\%04x\n",
$bus_nr, $addr;
}
if ($words) {
printf SAVEOUT "$words word values written to \%d-\%04x\n",
$bus_nr, $addr;
}
if (!$err && !$bytes && !$words) {
printf SAVEOUT "Only garbage found in dump file $dump\n";
$err = 1;
}
return $err;
}
if ($>) {
print "You must be root to use this script\n";
exit 1;
}
if (@ARGV < 2) {
print STDERR "Usage: i2c-stub-from-dump <addr>[,<addr>,...] <dump file> [<dump file> ...]\n";
exit 1;
}
# Check the parameters
@addr = split(/,/, shift @ARGV);
foreach (@addr) {
unless (m/^0x[0-7][0-9a-f]$/i) {
print STDERR "Invalid address $_\n";
exit 1;
}
$_ = oct $_;
}
if (@addr < @ARGV) {
print STDERR "Fewer addresses than dumps provided\n";
exit 4;
}
initialize_kernel_version();
if (@addr > 1 && !kernel_version_at_least(2, 6, 24)) {
print STDERR "Multiple addresses not supported by this kernel version\n";
exit 5;
}
$bus_nr = load_kernel_drivers(\@addr);
# We don't want to see the output of 256 i2cset
open(SAVEOUT, ">&STDOUT");
open(STDOUT, ">/dev/null");
foreach (@addr) {
if (!@ARGV) {
printf STDERR "Skipping \%d-\%04x, no dump file privided\n",
$bus_nr, $_;
next;
}
$err = process_dump($_, shift @ARGV);
last if $err;
}
close(STDOUT);
exit($err);

View file

@ -0,0 +1,52 @@
.TH I2C-STUB-FROM-DUMP 8 "March 2010"
.SH NAME
i2c-stub-from-dump \- feed i2c-stub with dump files
.SH SYNOPSIS
.B i2c-stub-from-dump
.IR address [, address ,...]
.IR dump-file " [" dump-file " ...]"
.SH DESCRIPTION
i2c-stub-from-dump is a small helper script for the i2c-stub kernel driver.
It lets you setup one or more fake I2C chips on the i2c-stub bus based on
dumps of the chips you want to emulate.
i2c-stub-from-dump requires i2cdetect and i2cset to be installed and
reachable through the user's PATH. The former is used to find out the i2c-stub
bus number, while the latter is used to write to the fake I2C chips.
.SH EXAMPLE
You have an I2C chip on system A. You would like to do some development on its
driver on system B. Here are the few steps you have to follow.
On system A, use i2cdump to capture a dump from the chip. Assuming that the
chip in question lives at address 0x4c on I2C bus 0, you would run:
i2cdump -y 0 0x4c b > chip.dump
Adjust the bus number and chip address for your case. i2cdetect can help
you find out their values. If the device uses word (16-bit) register
access instead of the traditional byte (8-bit) access, use mode \fBw\fR
instead of \fBb\fR.
Copy the dump file to system B.
On system B, run:
i2c-stub-from-dump 0x4c chip.dump
This will load the required i2c-dev and i2c-stub kernel drivers if needed,
then write all the register values to the emulated I2C chip at address 0x4c.
Again, adjust the address as needed.
.SH LIMITATIONS
There are some limitations to the kind of devices that can be handled:
.IP \(bu
Device must not have banks (as most Winbond devices do).
.SH SEE ALSO
i2cdump(8), i2cdetect(8), i2cset(8)
.SH AUTHOR
Jean Delvare