first commit
This commit is contained in:
commit
a5a0434432
1126 changed files with 439481 additions and 0 deletions
82
Script/i2c-tools-3.1.0/CHANGES
Normal file
82
Script/i2c-tools-3.1.0/CHANGES
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
i2c-tools CHANGES
|
||||
-----------------
|
||||
|
||||
3.1.0 (2011-12-04)
|
||||
decode-dimms: Decode module configuration type of DDR SDRAM
|
||||
Decode refresh rate of DDR SDRAM
|
||||
Add support for the at24 kernel driver
|
||||
i2c-dev.h: Make value arrays const for block write functions
|
||||
i2cset: Add support for SMBus and I2C block writes
|
||||
Removed obsolete method to specify value mask
|
||||
More stringent parameter validation
|
||||
|
||||
3.0.3 (2010-12-12)
|
||||
Makefile: Let the environment set CC and CFLAGS
|
||||
Integrate py-smbus into the build system
|
||||
README: Point users to the linux-i2c mailing list
|
||||
decode-dimms: Handle CRC of FB-DIMM and DDR3 SDRAM memory modules
|
||||
Add support for DDR3 SDRAM
|
||||
Fix decoding of SDR SDRAM bytes 12-14
|
||||
Add side-by-side formatting option
|
||||
Add merged cells formatting option
|
||||
Try harder to decode the manufacturing date
|
||||
Handle read errors on sysfs
|
||||
Decode voltage interface level of DDR SDRAM
|
||||
decode-xeon: Delete
|
||||
eepromer: Fix array initialization overrun
|
||||
i2cdetect: Drop legacy reference to ISA bus
|
||||
i2cset: Add support for short writes with PEC
|
||||
i2c-stub-from-dump: Use udev settle to speed up initialization
|
||||
Unload i2c-stub automatically if needed
|
||||
Add support for multiple dumps
|
||||
tools: Properly handle /dev/i2c not being a directory
|
||||
Increase limit on I2C bus number
|
||||
|
||||
3.0.2 (2008-11-29)
|
||||
i2c-dev.h: Drop I2C_FUNC_SMBUS_*I2C_BLOCK_2 defines
|
||||
decode-dimms: Add support for little-endian word hexdumps
|
||||
Only export the ceil function from POSIX
|
||||
decode-vaio: Remove history
|
||||
i2cdetect: Support i2c bus passed by name
|
||||
Shorten the usage message
|
||||
i2cdump: Support i2c bus passed by name
|
||||
Shorten the usage message
|
||||
Restrict the chip address to 0x03-0x77
|
||||
Split the functionality checking code into a separate function
|
||||
Better error message on missing adapter functionality
|
||||
i2cget: Support i2c bus passed by name
|
||||
Shorten the usage message
|
||||
Better error message on missing adapter functionality
|
||||
i2cset: Support i2c bus passed by name
|
||||
Shorten the usage message
|
||||
Restrict the chip address to 0x03-0x77
|
||||
Split the code into several functions for clarity
|
||||
Add support for short writes (SMBus send byte)
|
||||
Better error message on missing adapter functionality
|
||||
Set the data value mask with -m
|
||||
Make reading back the written value optional
|
||||
i2c-stub-from-dump: Add support for partial dumps
|
||||
Report if only garbage is found in dump file
|
||||
Behave properly when i2c-stub is already loaded
|
||||
Stop on i2cset error
|
||||
|
||||
3.0.1 (2008-04-04)
|
||||
Drop the trailing .pl from all perl script names
|
||||
decode-dimms: Fix DDR2 SDRAM module speed decoding
|
||||
Update manufacturer IDs
|
||||
Don't print anything by default if checksum fails
|
||||
Decode all DDR2 SDRAM timing information
|
||||
Add support for reading SPD data from hexdumps
|
||||
Make command line parsing more robust
|
||||
decode-vaio: Private data might not be readable by non-root users
|
||||
Print the asset tag
|
||||
Fix the timestamp decoding
|
||||
i2cdump: Fix I2C block mode error code
|
||||
Remove man page reference to hardware monitoring chips
|
||||
Let the user specify a register range
|
||||
i2cset: Final status messages go to stdout
|
||||
Return success even when readback fails or doesn't match
|
||||
i2c-stub-from-dump: New helper script to use with i2c-stub
|
||||
|
||||
3.0.0 (2007-10-14)
|
||||
Initial release
|
||||
339
Script/i2c-tools-3.1.0/COPYING
Normal file
339
Script/i2c-tools-3.1.0/COPYING
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
40
Script/i2c-tools-3.1.0/Makefile
Normal file
40
Script/i2c-tools-3.1.0/Makefile
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# I2C tools for Linux
|
||||
#
|
||||
# Copyright (C) 2007 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.
|
||||
|
||||
DESTDIR =
|
||||
prefix = /usr/local
|
||||
bindir = $(prefix)/bin
|
||||
sbindir = $(prefix)/sbin
|
||||
mandir = $(prefix)/share/man
|
||||
man8dir = $(mandir)/man8
|
||||
incdir = $(prefix)/include
|
||||
|
||||
INSTALL := install
|
||||
INSTALL_DATA := $(INSTALL) -m 644
|
||||
INSTALL_DIR := $(INSTALL) -m 755 -d
|
||||
INSTALL_PROGRAM := $(INSTALL) -m 755
|
||||
RM := rm -f
|
||||
|
||||
CC ?= gcc
|
||||
|
||||
CFLAGS ?= -O2
|
||||
# When debugging, use the following instead
|
||||
#CFLAGS := -O -g
|
||||
CFLAGS += -Wall
|
||||
|
||||
KERNELVERSION := $(shell uname -r)
|
||||
|
||||
.PHONY: all strip clean install uninstall
|
||||
|
||||
all:
|
||||
|
||||
EXTRA :=
|
||||
#EXTRA += py-smbus
|
||||
SRCDIRS := include eeprom stub tools $(EXTRA)
|
||||
include $(SRCDIRS:%=%/Module.mk)
|
||||
76
Script/i2c-tools-3.1.0/README
Normal file
76
Script/i2c-tools-3.1.0/README
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
I2C TOOLS FOR LINUX
|
||||
===================
|
||||
|
||||
This package contains an heterogeneous set of I2C tools for the Linux kernel.
|
||||
These tools were originally part of the lm-sensors project but were finally
|
||||
split into their own package for convenience. They compile, run and have been
|
||||
tested on GNU/Linux.
|
||||
|
||||
|
||||
CONTENTS
|
||||
--------
|
||||
|
||||
The various tools included in this package are grouped by category, each
|
||||
category has its own sub-directory:
|
||||
|
||||
* eeprom
|
||||
Perl scripts for decoding different types of EEPROMs (SPD, EDID...) These
|
||||
scripts rely on the "eeprom" kernel driver. They are installed by default.
|
||||
|
||||
* eepromer
|
||||
Tools for writing to EEPROMs. These tools rely on the "i2c-dev" kernel
|
||||
driver. They are not installed by default.
|
||||
|
||||
* include
|
||||
C/C++ header files for I2C and SMBus access over i2c-dev. Installed by
|
||||
default.
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
INSTALLATION
|
||||
------------
|
||||
|
||||
There's no configure script, so simply run "make" to build the tools, and
|
||||
"make install" to install them. You also can use "make uninstall" to remove
|
||||
all the files you installed. By default, files are installed in /usr/local
|
||||
but you can change this behavior by editing the Makefile file and setting
|
||||
prefix to wherever you want. You may change the C compiler and the
|
||||
compilation flags as well.
|
||||
|
||||
Optionally, you can run "make strip" prior to "make install" if you want
|
||||
smaller binaries. However, be aware that this will prevent any further
|
||||
attempt to debug the programs.
|
||||
|
||||
If you wish to include sub-directories that are not enabled by default, then
|
||||
just set them via the EXTRA make variable. For example, to build py-smbus,
|
||||
do:
|
||||
$ make EXTRA="py-smbus"
|
||||
|
||||
|
||||
DOCUMENTATION
|
||||
-------------
|
||||
|
||||
The main tools have manual pages, which are installed by "make install".
|
||||
See these manual pages for command line interface details and tool specific
|
||||
information.
|
||||
|
||||
The other tools come with simple text documentation, which isn't installed.
|
||||
|
||||
|
||||
QUESTIONS AND BUG REPORTS
|
||||
-------------------------
|
||||
|
||||
Please post your questions and bug reports to the linux-i2c mailing list:
|
||||
linux-i2c@vger.kernel.org
|
||||
For additional information about this list, see:
|
||||
http://vger.kernel.org/vger-lists.html#linux-i2c
|
||||
29
Script/i2c-tools-3.1.0/eeprom/Module.mk
Normal file
29
Script/i2c-tools-3.1.0/eeprom/Module.mk
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# EEPROM decoding scripts for the Linux eeprom 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.
|
||||
|
||||
EEPROM_DIR := eeprom
|
||||
|
||||
EEPROM_TARGETS := decode-dimms decode-vaio ddcmon decode-edid
|
||||
|
||||
#
|
||||
# Commands
|
||||
#
|
||||
|
||||
install-eeprom: $(addprefix $(EEPROM_DIR)/,$(EEPROM_TARGETS))
|
||||
$(INSTALL_DIR) $(DESTDIR)$(bindir)
|
||||
for program in $(EEPROM_TARGETS) ; do \
|
||||
$(INSTALL_PROGRAM) $(EEPROM_DIR)/$$program $(DESTDIR)$(bindir) ; done
|
||||
|
||||
uninstall-eeprom:
|
||||
for program in $(EEPROM_TARGETS) ; do \
|
||||
$(RM) $(DESTDIR)$(bindir)/$$program ; done
|
||||
|
||||
install: install-eeprom
|
||||
|
||||
uninstall: uninstall-eeprom
|
||||
18
Script/i2c-tools-3.1.0/eeprom/README
Normal file
18
Script/i2c-tools-3.1.0/eeprom/README
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
This directory contains scripts to decode the data exposed by the eeprom
|
||||
Linux kernel driver.
|
||||
|
||||
* decode-dimms (perl script)
|
||||
Decode the information found in memory module SPD EEPROMs. The SPD
|
||||
data is read either from the running system or from dump files.
|
||||
|
||||
* decode-vaio (perl script)
|
||||
Decode the information found in Sony Vaio laptop identification EEPROMs.
|
||||
|
||||
* ddcmon (perl script)
|
||||
decode-edid (perl script)
|
||||
Decode the information found in monitor EEPROMs. Both scripts require
|
||||
an access to the DDC channel of the monitor. This is typically provided
|
||||
by framebuffer drivers. decode-edid additionally requires parse-edid,
|
||||
which is part of the read-edid package. ddcmon prints general
|
||||
information, while decode-edid prints timing information for
|
||||
inclusion into your X11 configuration file.
|
||||
567
Script/i2c-tools-3.1.0/eeprom/ddcmon
Normal file
567
Script/i2c-tools-3.1.0/eeprom/ddcmon
Normal file
|
|
@ -0,0 +1,567 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Copyright (C) 2004-2005 Jean Delvare <khali@linux-fr.org>
|
||||
#
|
||||
# Parts inspired from decode-edid.
|
||||
# Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
|
||||
#
|
||||
# Parts inspired from the ddcmon driver and sensors' print_ddcmon function.
|
||||
# Copyright (C) 1998-2004 Mark D. Studebaker
|
||||
#
|
||||
# Parts inspired from the fbmon driver (Linux 2.6.10).
|
||||
# Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Version 1.0 2005-01-04 Jean Delvare <khali@linux-fr.org>
|
||||
#
|
||||
# This script is a replacement for the now deprecated ddcmon kernel driver.
|
||||
# Instead of having a dedicated driver, it is better to reuse the standard
|
||||
# eeprom driver and implement the EDID-specific code in user-space.
|
||||
#
|
||||
# EDID (Extended Display Identification Data) is a VESA standard which
|
||||
# allows storing (on manufacturer's side) and retrieving (on user's side)
|
||||
# of configuration information about displays, such as manufacturer,
|
||||
# serial number, physical dimensions and allowed horizontal and vertical
|
||||
# refresh rates.
|
||||
#
|
||||
# Syntax: ddcmon [bus [address]]
|
||||
# Address can be given in decimal or hexadecimal (with a 0x prefix).
|
||||
# If no address is given, default is 0x50.
|
||||
# Bus number must be given in decimal. If no bus number is given,
|
||||
# try them all.
|
||||
|
||||
use strict;
|
||||
use Fcntl qw(:DEFAULT :seek);
|
||||
use vars qw(@standard_scales);
|
||||
|
||||
@standard_scales = ([1, 1], [3, 4], [4, 5], [16, 9]);
|
||||
|
||||
# Make sure the eeprom module is loaded.
|
||||
# For non-modular kernels, we can't help.
|
||||
if (-r '/proc/modules')
|
||||
{
|
||||
my $found = 0;
|
||||
open(MODULES, '/proc/modules');
|
||||
while (!$found && defined ($_ = <MODULES>))
|
||||
{
|
||||
$found++ if m/^eeprom\s+/;
|
||||
}
|
||||
close(MODULES);
|
||||
|
||||
unless ($found)
|
||||
{
|
||||
print STDERR
|
||||
"This script requires the eeprom module to be loaded.\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Only used for sysfs
|
||||
sub rawread
|
||||
{
|
||||
my $filename = shift;
|
||||
my $length = shift;
|
||||
my $offset = shift || 0;
|
||||
my $bytes = '';
|
||||
|
||||
sysopen(FH, $filename, O_RDONLY)
|
||||
or die "Can't open $filename";
|
||||
if ($offset)
|
||||
{
|
||||
sysseek(FH, $offset, SEEK_SET)
|
||||
or die "Can't seek in $filename";
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
while ($length)
|
||||
{
|
||||
my $r = sysread(FH, $bytes, $length, $offset);
|
||||
die "Can't read $filename"
|
||||
unless defined($r);
|
||||
die "Unexpected EOF in $filename"
|
||||
unless $r;
|
||||
$offset += $r;
|
||||
$length -= $r;
|
||||
}
|
||||
close(FH);
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
sub get_edid_sysfs
|
||||
{
|
||||
my ($bus, $addr) = @_;
|
||||
|
||||
my @bytes = unpack("C*", rawread("/sys/bus/i2c/devices/$bus-00$addr/eeprom", 128));
|
||||
|
||||
return \@bytes;
|
||||
}
|
||||
|
||||
sub get_edid_procfs
|
||||
{
|
||||
my ($bus, $addr) = @_;
|
||||
|
||||
my @bytes;
|
||||
|
||||
for (my $i = 0 ; $i < 0x80; $i += 0x10)
|
||||
{
|
||||
my $filename = sprintf("/proc/sys/dev/sensors/eeprom-i2c-\%s-\%s/\%02x",
|
||||
$bus, $addr, $i);
|
||||
open(EEDATA, $filename)
|
||||
or die "Can't read $filename";
|
||||
push @bytes, split(/\s+/, <EEDATA>);
|
||||
close(EEDATA);
|
||||
}
|
||||
|
||||
return \@bytes;
|
||||
}
|
||||
|
||||
sub print_line
|
||||
{
|
||||
my $label = shift;
|
||||
my $pattern = shift;
|
||||
|
||||
printf("\%-24s$pattern\n", $label.':', @_);
|
||||
}
|
||||
|
||||
sub extract_byte
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
return $bytes->[$offset];
|
||||
}
|
||||
|
||||
sub extract_word
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
return ($bytes->[$offset]
|
||||
| ($bytes->[$offset+1] << 8));
|
||||
}
|
||||
|
||||
sub extract_manufacturer
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
my $i = ($bytes->[$offset+1] | ($bytes->[$offset] << 8));
|
||||
|
||||
return sprintf('%c%c%c',
|
||||
(($i >> 10) & 0x1f) + ord('A') - 1,
|
||||
(($i >> 5) & 0x1f) + ord('A') - 1,
|
||||
($i & 0x1f) + ord('A') - 1);
|
||||
}
|
||||
|
||||
sub extract_sesquiword
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
return ($bytes->[$offset]
|
||||
| ($bytes->[$offset+1] << 8)
|
||||
| ($bytes->[$offset+2] << 16));
|
||||
}
|
||||
|
||||
sub extract_dword
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
return ($bytes->[$offset]
|
||||
| ($bytes->[$offset+1] << 8)
|
||||
| ($bytes->[$offset+2] << 16)
|
||||
| ($bytes->[$offset+3] << 24));
|
||||
}
|
||||
|
||||
sub extract_display_input
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
my @voltage = ('0.700V/0.300V', '0.714V/0.286V',
|
||||
'1.000V/0.400V', '0.700V/0.000V');
|
||||
|
||||
return 'Digital'
|
||||
if ($bytes->[$offset] & 0x80);
|
||||
|
||||
return 'Analog ('.$voltage[($bytes->[$offset] & 0x60) >> 5].')';
|
||||
}
|
||||
|
||||
sub extract_dpms
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
my @supported;
|
||||
|
||||
push @supported, 'Active Off' if ($bytes->[$offset] & 0x20);
|
||||
push @supported, 'Suspend' if ($bytes->[$offset] & 0x40);
|
||||
push @supported, 'Standby' if ($bytes->[$offset] & 0x80);
|
||||
|
||||
return join(', ', @supported)
|
||||
if (@supported);
|
||||
|
||||
return 'None supported';
|
||||
}
|
||||
|
||||
sub extract_color_mode
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
|
||||
my @mode = ('Monochrome', 'RGB Multicolor', 'Non-RGB Multicolor');
|
||||
|
||||
return $mode[($bytes->[$offset] >> 3) & 0x03];
|
||||
}
|
||||
|
||||
sub good_signature
|
||||
{
|
||||
my $bytes = shift;
|
||||
|
||||
return $bytes->[0] == 0x00
|
||||
&& $bytes->[1] == 0xff
|
||||
&& $bytes->[2] == 0xff
|
||||
&& $bytes->[3] == 0xff
|
||||
&& $bytes->[4] == 0xff
|
||||
&& $bytes->[5] == 0xff
|
||||
&& $bytes->[6] == 0xff
|
||||
&& $bytes->[7] == 0x00;
|
||||
}
|
||||
|
||||
sub verify_checksum
|
||||
{
|
||||
my $bytes = shift;
|
||||
my $cs;
|
||||
|
||||
for (my $i = 0, $cs = 0; $i < 0x80; $i++)
|
||||
{
|
||||
$cs += $bytes->[$i];
|
||||
}
|
||||
|
||||
return (($cs & 0xff) == 0 ? 'OK' : 'Not OK');
|
||||
}
|
||||
|
||||
sub add_timing
|
||||
{
|
||||
my ($timings, $new) = @_;
|
||||
|
||||
my $mode = sprintf('%ux%u@%u%s', $new->[0], $new->[1],
|
||||
$new->[2], defined ($new->[3]) &&
|
||||
$new->[3] eq 'interlaced' ? 'i' : '');
|
||||
|
||||
$timings->{$mode} = $new;
|
||||
}
|
||||
|
||||
sub add_standard_timing
|
||||
{
|
||||
my ($timings, $byte0, $byte1) = @_;
|
||||
|
||||
# Unused slot
|
||||
return if ($byte0 == $byte1)
|
||||
&& ($byte0 == 0x01 || $byte0 == 0x00 || $byte0 == 0x20);
|
||||
|
||||
my $width = ($byte0 + 31) * 8;
|
||||
my $height = $width * $standard_scales[$byte1 >> 6]->[0]
|
||||
/ $standard_scales[$byte1 >> 6]->[1];
|
||||
my $refresh = 60 + ($byte1 & 0x3f);
|
||||
|
||||
add_timing($timings, [$width, $height, $refresh]);
|
||||
}
|
||||
|
||||
sub sort_timings
|
||||
{
|
||||
# First order by width
|
||||
return -1 if $a->[0] < $b->[0];
|
||||
return 1 if $a->[0] > $b->[0];
|
||||
|
||||
# Second by height
|
||||
return -1 if $a->[1] < $b->[1];
|
||||
return 1 if $a->[1] > $b->[1];
|
||||
|
||||
# Third by frequency
|
||||
# Interlaced modes count for half their frequency
|
||||
my $freq_a = $a->[2];
|
||||
my $freq_b = $b->[2];
|
||||
$freq_a /= 2 if defined $a->[3] && $a->[3] eq 'interlaced';
|
||||
$freq_b /= 2 if defined $b->[3] && $b->[3] eq 'interlaced';
|
||||
return -1 if $freq_a < $freq_b;
|
||||
return 1 if $freq_a > $freq_b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub print_timings
|
||||
{
|
||||
my ($bytes, $timings) = @_;
|
||||
|
||||
# Established Timings
|
||||
my @established =
|
||||
(
|
||||
[720, 400, 70],
|
||||
[720, 400, 88],
|
||||
[640, 480, 60],
|
||||
[640, 480, 67],
|
||||
[640, 480, 72],
|
||||
[640, 480, 75],
|
||||
[800, 600, 56],
|
||||
[800, 600, 60],
|
||||
[800, 600, 72],
|
||||
[800, 600, 75],
|
||||
[832, 624, 75],
|
||||
[1024, 768, 87, 'interlaced'],
|
||||
[1024, 768, 60],
|
||||
[1024, 768, 70],
|
||||
[1024, 768, 75],
|
||||
[1280, 1024, 75],
|
||||
undef, undef, undef,
|
||||
[1152, 870, 75],
|
||||
);
|
||||
my $temp = extract_sesquiword($bytes, 0x23);
|
||||
for (my $i = 0; $i < 24; $i++)
|
||||
{
|
||||
next unless defined($established[$i]);
|
||||
add_timing($timings, $established[$i])
|
||||
if ($temp & (1 << $i));
|
||||
}
|
||||
|
||||
# Standard Timings
|
||||
for (my $i = 0x26; $i < 0x36; $i += 2)
|
||||
{
|
||||
add_standard_timing($timings, $bytes->[$i], $bytes->[$i+1]);
|
||||
}
|
||||
|
||||
foreach my $v (sort sort_timings values(%{$timings}))
|
||||
{
|
||||
print_line("Timing", '%ux%u @ %u Hz%s',
|
||||
$v->[0], $v->[1], $v->[2],
|
||||
defined($v->[3]) ? ' ('.$v->[3].')' : '');
|
||||
}
|
||||
}
|
||||
|
||||
sub extract_string
|
||||
{
|
||||
my ($bytes, $offset) = @_;
|
||||
my $string = '';
|
||||
|
||||
for (my $i = 5; $i < 18; $i++)
|
||||
{
|
||||
last if $bytes->[$offset+$i] == 0x0a
|
||||
|| $bytes->[$offset+$i] == 0x00;
|
||||
$string .= chr($bytes->[$offset+$i])
|
||||
if ($bytes->[$offset+$i] >= 32
|
||||
&& $bytes->[$offset+$i] < 127);
|
||||
}
|
||||
$string =~ s/\s+$//;
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
# Some blocks contain different information:
|
||||
# 0x00, 0x00, 0x00, 0xfa: Additional standard timings block
|
||||
# 0x00, 0x00, 0x00, 0xfc: Monitor block
|
||||
# 0x00, 0x00, 0x00, 0xfd: Limits block
|
||||
# 0x00, 0x00, 0x00, 0xfe: Ascii block
|
||||
# 0x00, 0x00, 0x00, 0xff: Serial block
|
||||
# Return a reference to a hash containing all information.
|
||||
sub extract_detailed_timings
|
||||
{
|
||||
my ($bytes) = @_;
|
||||
|
||||
my %info = ('timings' => {});
|
||||
|
||||
for (my $offset = 0x36; $offset < 0x7e; $offset += 18)
|
||||
{
|
||||
if ($bytes->[$offset] == 0x00
|
||||
&& $bytes->[$offset+1] == 0x00
|
||||
&& $bytes->[$offset+2] == 0x00
|
||||
&& $bytes->[$offset+4] == 0x00)
|
||||
{
|
||||
if ($bytes->[$offset+3] == 0xfa)
|
||||
{
|
||||
for (my $i = $offset + 5; $i < $offset + 17; $i += 2)
|
||||
{
|
||||
add_standard_timing($info{'timings'},
|
||||
$bytes->[$i],
|
||||
$bytes->[$i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
elsif ($bytes->[$offset+3] == 0xfc)
|
||||
{
|
||||
$info{'monitor'} .= extract_string($bytes, $offset);
|
||||
}
|
||||
|
||||
elsif ($bytes->[$offset+3] == 0xfd)
|
||||
{
|
||||
$info{'limits'}{'vsync_min'} = $bytes->[$offset+5];
|
||||
$info{'limits'}{'vsync_max'} = $bytes->[$offset+6];
|
||||
$info{'limits'}{'hsync_min'} = $bytes->[$offset+7];
|
||||
$info{'limits'}{'hsync_max'} = $bytes->[$offset+8];
|
||||
$info{'limits'}{'clock_max'} = $bytes->[$offset+9];
|
||||
}
|
||||
|
||||
elsif ($bytes->[$offset+3] == 0xfe)
|
||||
{
|
||||
$info{'ascii'} .= extract_string($bytes, $offset);
|
||||
}
|
||||
|
||||
elsif ($bytes->[$offset+3] == 0xff)
|
||||
{
|
||||
$info{'serial'} .= extract_string($bytes, $offset);
|
||||
}
|
||||
|
||||
next;
|
||||
}
|
||||
|
||||
# Detailed Timing
|
||||
my $width = $bytes->[$offset+2] + (($bytes->[$offset+4] & 0xf0) << 4);
|
||||
my $height = $bytes->[$offset+5] + (($bytes->[$offset+7] & 0xf0) << 4);
|
||||
my $clock = extract_word($bytes, $offset) * 10000;
|
||||
my $hblank = $bytes->[$offset+3] + (($bytes->[$offset+4] & 0x0f) << 8);
|
||||
my $vblank = $bytes->[$offset+6] + (($bytes->[$offset+7] & 0x0f) << 8);
|
||||
my $area = ($width + $hblank) * ($height + $vblank);
|
||||
next unless $area; # Should not happen, but...
|
||||
my $refresh = ($clock + $area / 2) / $area; # Proper rounding
|
||||
add_timing($info{'timings'}, [$width, $height, $refresh]);
|
||||
}
|
||||
|
||||
return \%info;
|
||||
}
|
||||
|
||||
sub print_edid
|
||||
{
|
||||
my ($bus, $address) = @_;
|
||||
my $bytes;
|
||||
|
||||
if (-r "/sys/bus/i2c/devices/$bus-00$address/eeprom")
|
||||
{
|
||||
$bytes = get_edid_sysfs($bus, $address);
|
||||
}
|
||||
elsif (-r "/proc/sys/dev/sensors/eeprom-i2c-$bus-$address/00")
|
||||
{
|
||||
$bytes = get_edid_procfs($bus, $address);
|
||||
}
|
||||
|
||||
return 1 unless defined $bytes;
|
||||
return 2 unless good_signature($bytes);
|
||||
|
||||
print_line('Checksum', '%s', verify_checksum($bytes));
|
||||
my $edid_version = extract_byte($bytes, 0x12);
|
||||
my $edid_revision = extract_byte($bytes, 0x13);
|
||||
print_line('EDID Version', '%u.%u', $edid_version,
|
||||
$edid_revision);
|
||||
if ($edid_version > 1 || $edid_revision > 2)
|
||||
{
|
||||
$standard_scales[0][0] = 16;
|
||||
$standard_scales[0][1] = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
$standard_scales[0][0] = 1;
|
||||
$standard_scales[0][1] = 1;
|
||||
}
|
||||
|
||||
my $info = extract_detailed_timings($bytes);
|
||||
|
||||
print_line('Manufacturer ID', '%s', extract_manufacturer($bytes, 0x08));
|
||||
print_line('Model Number', '0x%04X', extract_word($bytes, 0x0A));
|
||||
print_line('Model Name', '%s', $info->{'monitor'})
|
||||
if defined $info->{'monitor'};
|
||||
|
||||
if ($info->{'serial'})
|
||||
{
|
||||
print_line('Serial Number', '%s', $info->{'serial'})
|
||||
}
|
||||
elsif ((my $temp = extract_dword($bytes, 0x0C)))
|
||||
{
|
||||
print_line('Serial Number', '%u', $temp)
|
||||
}
|
||||
|
||||
print_line('Manufacture Time', '%u-W%02u',
|
||||
1990 + extract_byte($bytes, 0x11),
|
||||
extract_byte($bytes, 0x10));
|
||||
print_line('Display Input', '%s', extract_display_input($bytes, 0x14));
|
||||
print_line('Monitor Size (cm)', '%ux%u', extract_byte($bytes, 0x15),
|
||||
extract_byte($bytes, 0x16));
|
||||
print_line('Gamma Factor', '%.2f',
|
||||
1 + extract_byte($bytes, 0x17) / 100.0);
|
||||
print_line('DPMS Modes', '%s', extract_dpms($bytes, 0x18));
|
||||
print_line('Color Mode', '%s', extract_color_mode($bytes, 0x18))
|
||||
if (($bytes->[0x18] & 0x18) != 0x18);
|
||||
print_line('Additional Info', '%s', $info->{'ascii'})
|
||||
if $info->{'ascii'};
|
||||
|
||||
if (defined($info->{'limits'}))
|
||||
{
|
||||
print_line('Vertical Sync (Hz)', '%u-%u',
|
||||
$info->{'limits'}{'vsync_min'},
|
||||
$info->{'limits'}{'vsync_max'});
|
||||
print_line('Horizontal Sync (kHz)', '%u-%u',
|
||||
$info->{'limits'}{'hsync_min'},
|
||||
$info->{'limits'}{'hsync_max'});
|
||||
print_line('Max Pixel Clock (MHz)', '%u',
|
||||
$info->{'limits'}{'clock_max'} * 10)
|
||||
unless $info->{'limits'}{'clock_max'} == 0xff;
|
||||
}
|
||||
|
||||
print_timings($bytes, $info->{'timings'});
|
||||
print("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Get the address. Default to 0x50 if not given.
|
||||
my $address;
|
||||
if (defined($ARGV[1]))
|
||||
{
|
||||
$address = $ARGV[1];
|
||||
# Convert to decimal, whatever the value.
|
||||
$address = oct $address if $address =~ m/^0/;
|
||||
# Convert to an hexadecimal string.
|
||||
$address = sprintf '%02x', $address;
|
||||
}
|
||||
else
|
||||
{
|
||||
$address = '50';
|
||||
}
|
||||
|
||||
if (defined($ARGV[0]))
|
||||
{
|
||||
my $error = print_edid($ARGV[0], $address);
|
||||
|
||||
if ($error == 1)
|
||||
{
|
||||
print STDERR
|
||||
"No EEPROM found at 0x$address on bus $ARGV[0].\n";
|
||||
exit 1;
|
||||
}
|
||||
elsif ($error == 2)
|
||||
{
|
||||
print STDERR
|
||||
"EEPROM found at 0x$address on bus $ARGV[0], but is not an EDID EEPROM.\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
# If no bus is given, try them all.
|
||||
else
|
||||
{
|
||||
my $total = 0;
|
||||
|
||||
for (my $i = 0; $i < 16; $i++)
|
||||
{
|
||||
$total++ unless print_edid($i, $address);
|
||||
}
|
||||
|
||||
unless ($total)
|
||||
{
|
||||
print STDERR
|
||||
"No EDID EEPROM found.\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
1987
Script/i2c-tools-3.1.0/eeprom/decode-dimms
Normal file
1987
Script/i2c-tools-3.1.0/eeprom/decode-dimms
Normal file
File diff suppressed because it is too large
Load diff
225
Script/i2c-tools-3.1.0/eeprom/decode-edid
Normal file
225
Script/i2c-tools-3.1.0/eeprom/decode-edid
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Copyright (C) 2003-2006 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.
|
||||
#
|
||||
# Version 0.1 2003-07-17 Jean Delvare <khali@linux-fr.org>
|
||||
# Version 0.2 2003-07-22 Jean Delvare <khali@linux-fr.org>
|
||||
# Use print instead of syswrite.
|
||||
# Version 0.3 2003-08-24 Jean Delvare <khali@linux-fr.org>
|
||||
# Fix data block length (128 bytes instead of 256).
|
||||
# Version 1.0 2004-02-08 Jean Delvare <khali@linux-fr.org>
|
||||
# Added support for Linux 2.5/2.6 (i.e. sysfs).
|
||||
# Version 1.1 2006-09-01 Jean Delvare <khali@linux-fr.org>
|
||||
# Append /usr/sbin or /usr/local/sbin to $PATH if needed.
|
||||
#
|
||||
# EEPROM data decoding for EDID. EDID (Extended Display Identification
|
||||
# Data) is a VESA standard which allows storing (on manufacturer's side)
|
||||
# and retrieving (on user's side) of configuration information about
|
||||
# displays, such as manufacturer, serial number, physical dimensions and
|
||||
# allowed horizontal and vertical refresh rates.
|
||||
#
|
||||
# Using the eeprom kernel driver, you have two possibilities to
|
||||
# make use of these data:
|
||||
# 1* The ddcmon script.
|
||||
# 2* This script.
|
||||
# Both solutions will return a different kind of information. The first
|
||||
# method will report user-interesting information, such as the model number
|
||||
# or the year of manufacturing. The second method will report video-card-
|
||||
# interesting information, such as video modes and refresh rates.
|
||||
#
|
||||
# Note that this script does almost nothing by itself. It simply converts
|
||||
# what it finds in /proc to binary data to feed the parse-edid program.
|
||||
# The parse-edid program was written by John Fremlin and is available at
|
||||
# the following address:
|
||||
# http://john.fremlin.de/programs/linux/read-edid/
|
||||
|
||||
use strict;
|
||||
use Fcntl qw(:DEFAULT :seek);
|
||||
use vars qw($bus $address);
|
||||
use constant PROCFS => 1;
|
||||
use constant SYSFS => 2;
|
||||
|
||||
# parse-edid will typically be installed in /usr/sbin or /usr/local/sbin
|
||||
# even though regular users can run it
|
||||
$ENV{PATH} .= ':/usr/local/sbin'
|
||||
if $ENV{PATH} !~ m,(^|:)/usr/local/sbin/?(:|$),
|
||||
&& -x '/usr/local/sbin/parse-edid';
|
||||
$ENV{PATH} .= ':/usr/sbin'
|
||||
if $ENV{PATH} !~ m,(^|:)/usr/sbin/?(:|$),
|
||||
&& -x '/usr/sbin/parse-edid';
|
||||
|
||||
sub edid_valid_procfs
|
||||
{
|
||||
my ($bus, $addr) = @_;
|
||||
|
||||
open EEDATA, "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/00";
|
||||
my $line = <EEDATA>;
|
||||
close EEDATA;
|
||||
return 1
|
||||
if $line =~ m/^0 255 255 255 255 255 255 0 /;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Only used for sysfs
|
||||
sub rawread
|
||||
{
|
||||
my ($filename, $length, $offset) = @_;
|
||||
my $bytes = '';
|
||||
|
||||
sysopen(FH, $filename, O_RDONLY)
|
||||
or die "Can't open $filename";
|
||||
if ($offset)
|
||||
{
|
||||
sysseek(FH, $offset, SEEK_SET)
|
||||
or die "Can't seek in $filename";
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
while ($length)
|
||||
{
|
||||
my $r = sysread(FH, $bytes, $length, $offset);
|
||||
die "Can't read $filename"
|
||||
unless defined($r);
|
||||
die "Unexpected EOF in $filename"
|
||||
unless $r;
|
||||
$offset += $r;
|
||||
$length -= $r;
|
||||
}
|
||||
close(FH);
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
sub edid_valid_sysfs
|
||||
{
|
||||
my ($bus, $addr) = @_;
|
||||
my $bytes = rawread("/sys/bus/i2c/devices/$bus-00$addr/eeprom", 8, 0);
|
||||
|
||||
return 1
|
||||
if $bytes eq "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00";
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub bus_detect
|
||||
{
|
||||
my $max = shift;
|
||||
|
||||
for (my $i=0; $i<$max; $i++)
|
||||
{
|
||||
if (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-50/00")
|
||||
{
|
||||
if (edid_valid_procfs($i, '50'))
|
||||
{
|
||||
print STDERR
|
||||
"decode-edid: using bus $i (autodetected)\n";
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
elsif (-r "/sys/bus/i2c/devices/$i-0050/eeprom")
|
||||
{
|
||||
if (edid_valid_sysfs($i, '50'))
|
||||
{
|
||||
print STDERR
|
||||
"decode-edid: using bus $i (autodetected)\n";
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return; # default
|
||||
}
|
||||
|
||||
sub edid_decode
|
||||
{
|
||||
my ($bus, $addr, $mode) = @_;
|
||||
|
||||
# Make sure it is an EDID EEPROM.
|
||||
|
||||
unless (($mode == PROCFS && edid_valid_procfs ($bus, $addr))
|
||||
|| ($mode == SYSFS && edid_valid_sysfs ($bus, $addr)))
|
||||
{
|
||||
print STDERR
|
||||
"decode-edid: not an EDID EEPROM at $bus-$addr\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$SIG{__WARN__} = sub { };
|
||||
open PIPE, "| parse-edid"
|
||||
or die "Can't open parse-edid. Please install read-edid.\n";
|
||||
delete $SIG{__WARN__};
|
||||
binmode PIPE;
|
||||
|
||||
if ($mode == PROCFS)
|
||||
{
|
||||
for (my $i=0; $i<=0x70; $i+=0x10)
|
||||
{
|
||||
my $file = sprintf '%02x', $i;
|
||||
my $output = '';
|
||||
open EEDATA, "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/$file"
|
||||
or die "Can't read /proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/$file";
|
||||
while(<EEDATA>)
|
||||
{
|
||||
foreach my $item (split)
|
||||
{
|
||||
$output .= pack "C", $item;
|
||||
}
|
||||
}
|
||||
close EEDATA;
|
||||
print PIPE $output;
|
||||
}
|
||||
}
|
||||
elsif ($mode == SYSFS)
|
||||
{
|
||||
print PIPE rawread("/sys/bus/i2c/devices/$bus-00$address/eeprom", 128, 0);
|
||||
}
|
||||
|
||||
close PIPE;
|
||||
}
|
||||
|
||||
# Get the address. Default to 0x50 if not given.
|
||||
$address = $ARGV[1] || 0x50;
|
||||
# Convert to decimal, whatever the value.
|
||||
$address = oct $address if $address =~ m/^0/;
|
||||
# Convert to an hexadecimal string.
|
||||
$address = sprintf '%02x', $address;
|
||||
|
||||
# Get the bus. Try to autodetect if not given.
|
||||
$bus = $ARGV[0] if defined $ARGV[0];
|
||||
$bus = bus_detect(8) unless defined $bus;
|
||||
|
||||
if(defined $bus)
|
||||
{
|
||||
print STDERR
|
||||
"decode-edid: decode-edid version 1.1\n";
|
||||
if (-r "/proc/sys/dev/sensors/eeprom-i2c-$bus-$address")
|
||||
{
|
||||
edid_decode ($bus, $address, PROCFS);
|
||||
exit 0;
|
||||
}
|
||||
elsif (-r "/sys/bus/i2c/devices/$bus-00$address")
|
||||
{
|
||||
edid_decode ($bus, $address, SYSFS);
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
print STDERR
|
||||
"EDID EEPROM not found. Please make sure that the eeprom module is loaded.\n";
|
||||
print STDERR
|
||||
"Maybe your EDID EEPROM is on another bus. Try \"decode-edid ".($bus+1)."\".\n"
|
||||
if defined $bus;
|
||||
237
Script/i2c-tools-3.1.0/eeprom/decode-vaio
Normal file
237
Script/i2c-tools-3.1.0/eeprom/decode-vaio
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Copyright (C) 2002-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.
|
||||
#
|
||||
# EEPROM data decoding for Sony Vaio laptops.
|
||||
#
|
||||
# The eeprom driver must be loaded. For kernels older than 2.6.0, the
|
||||
# eeprom driver can be found in the lm-sensors package.
|
||||
#
|
||||
# Please note that this is a guess-only work. Sony support refused to help
|
||||
# me, so if someone can provide information, please contact me.
|
||||
# My knowledge is summarized on this page:
|
||||
# http://khali.linux-fr.org/vaio/eeprom.html
|
||||
#
|
||||
# It seems that if present, the EEPROM is always at 0x57.
|
||||
#
|
||||
# Models tested so far:
|
||||
# PCG-F403 : No EEPROM
|
||||
# PCG-F707 : No EEPROM
|
||||
# PCG-GR114EK : OK
|
||||
# PCG-GR114SK : OK
|
||||
# PCG-GR214EP : OK
|
||||
# PCG-GRT955MP : OK
|
||||
# PCG-GRX316G : OK
|
||||
# PCG-GRX570 : OK
|
||||
# PCG-GRX600K : OK
|
||||
# PCG-U1 : OK
|
||||
# PCG-Z600LEK : No EEPROM
|
||||
# PCG-Z600NE : No EEPROM
|
||||
# VGN-S260 : OK
|
||||
# VGN-S4M/S : OK
|
||||
# VGN-TZ11MN/N : OK
|
||||
#
|
||||
# Thanks to Werner Heuser, Carsten Blume, Christian Gennerat, Joe Wreschnig,
|
||||
# Xavier Roche, Sebastien Lefevre, Lars Heer, Steve Dobson, Kent Hunt,
|
||||
# Timo Hoenig and others for their precious help.
|
||||
|
||||
|
||||
use strict;
|
||||
use Fcntl qw(:DEFAULT :seek);
|
||||
use vars qw($sysfs $found);
|
||||
|
||||
use constant VERSION => "1.6";
|
||||
use constant ONLYROOT => "Readable only by root";
|
||||
|
||||
sub print_item
|
||||
{
|
||||
my ($label,$value) = @_;
|
||||
|
||||
printf("\%16s : \%s\n",$label,$value);
|
||||
}
|
||||
|
||||
# Abstract reads so that other functions don't have to care wether
|
||||
# we need to use procfs or sysfs
|
||||
sub read_eeprom_bytes
|
||||
{
|
||||
my ($bus, $addr, $offset, $length) = @_;
|
||||
my $filename;
|
||||
|
||||
if ($sysfs)
|
||||
{
|
||||
$filename = "/sys/bus/i2c/devices/$bus-00$addr/eeprom";
|
||||
sysopen(FH, $filename, O_RDONLY)
|
||||
or die "Can't open $filename";
|
||||
sysseek(FH, $offset, SEEK_SET)
|
||||
or die "Can't seek in $filename";
|
||||
|
||||
my ($r, $bytes);
|
||||
$bytes = '';
|
||||
$offset = 0;
|
||||
while($length)
|
||||
{
|
||||
$r = sysread(FH, $bytes, $length, $offset);
|
||||
die "Can't read $filename"
|
||||
unless defined($r);
|
||||
die "Unexpected EOF in $filename"
|
||||
unless $r;
|
||||
$offset += $r;
|
||||
$length -= $r;
|
||||
}
|
||||
close(FH);
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
my $base = $offset & 0xf0;
|
||||
$offset -= $base;
|
||||
my $values = '';
|
||||
my $remains = $length + $offset;
|
||||
|
||||
# Get all lines in a single string
|
||||
while ($remains > 0)
|
||||
{
|
||||
$filename = "/proc/sys/dev/sensors/eeprom-i2c-$bus-$addr/"
|
||||
. sprintf('%02x', $base);
|
||||
open(FH, $filename)
|
||||
or die "Can't open $filename";
|
||||
$values .= <FH>;
|
||||
close(FH);
|
||||
$remains -= 16;
|
||||
$base += 16;
|
||||
}
|
||||
|
||||
# Store the useful part in an array
|
||||
my @bytes = split(/[ \n]/, $values);
|
||||
@bytes = @bytes[$offset..$offset+$length-1];
|
||||
|
||||
# Back to a binary string
|
||||
return pack('C*', @bytes);
|
||||
}
|
||||
}
|
||||
|
||||
sub decode_string
|
||||
{
|
||||
my ($bus, $addr, $offset, $length) = @_;
|
||||
|
||||
my $string = read_eeprom_bytes($bus, $addr, $offset, $length);
|
||||
$string =~ s/\x00.*$//;
|
||||
|
||||
return($string);
|
||||
}
|
||||
|
||||
sub decode_hexa
|
||||
{
|
||||
my ($bus, $addr, $offset, $length) = @_;
|
||||
|
||||
my @bytes = unpack('C*', read_eeprom_bytes($bus, $addr, $offset, $length));
|
||||
my $string='';
|
||||
|
||||
for(my $i=0;$i<$length;$i++)
|
||||
{
|
||||
$string.=sprintf('%02X', shift(@bytes));
|
||||
}
|
||||
|
||||
return($string);
|
||||
}
|
||||
|
||||
sub decode_uuid
|
||||
{
|
||||
my ($bus,$addr,$base) = @_;
|
||||
|
||||
my @bytes = unpack('C16', read_eeprom_bytes($bus, $addr, $base, 16));
|
||||
my $string='';
|
||||
|
||||
for(my $i=0;$i<16;$i++)
|
||||
{
|
||||
$string.=sprintf('%02x',shift(@bytes));
|
||||
if(($i==3)||($i==5)||($i==7)||($i==9))
|
||||
{
|
||||
$string.='-';
|
||||
}
|
||||
}
|
||||
|
||||
if ($string eq '00000000-0000-0000-0000-000000000000')
|
||||
{
|
||||
return(ONLYROOT);
|
||||
}
|
||||
else
|
||||
{
|
||||
return($string);
|
||||
}
|
||||
}
|
||||
|
||||
sub vaio_decode
|
||||
{
|
||||
my ($bus,$addr) = @_;
|
||||
|
||||
my $name = decode_string($bus, $addr, 128, 32);
|
||||
# Simple heuristic to skip false positives
|
||||
return 0 unless $name =~ m/^[A-Z-]{4}/;
|
||||
|
||||
print_item('Machine Name', $name);
|
||||
my $serial = decode_string($bus, $addr, 192, 32);
|
||||
print_item('Serial Number', $serial ? $serial : ONLYROOT);
|
||||
print_item('UUID', decode_uuid($bus, $addr, 16));
|
||||
my $revision = decode_string($bus, $addr, 160, 10);
|
||||
print_item(length($revision) > 2 ? 'Service Tag' : 'Revision',
|
||||
$revision);
|
||||
print_item('Asset Tag', decode_string($bus, $addr, 170, 4).
|
||||
decode_hexa($bus, $addr, 174, 12));
|
||||
print_item('OEM Data', decode_string($bus, $addr, 32, 16));
|
||||
print_item('Timestamp', decode_string($bus, $addr, 224, 18));
|
||||
return 1;
|
||||
}
|
||||
|
||||
BEGIN
|
||||
{
|
||||
print("# Sony Vaio EEPROM Decoder version ".VERSION." by Jean Delvare\n\n");
|
||||
}
|
||||
|
||||
END
|
||||
{
|
||||
print("\n");
|
||||
}
|
||||
|
||||
for (my $i = 0, $found=0; $i <= 4 && !$found; $i++)
|
||||
{
|
||||
if (-r "/sys/bus/i2c/devices/$i-0057/eeprom")
|
||||
{
|
||||
$sysfs = 1;
|
||||
$found += vaio_decode($i, '57');
|
||||
}
|
||||
elsif (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-57")
|
||||
{
|
||||
if (-r "/proc/sys/dev/sensors/eeprom-i2c-$i-57/data0-15")
|
||||
{
|
||||
print("Deprecated old interface found. Please upgrade to lm_sensors 2.6.3 or greater.");
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sysfs = 0;
|
||||
$found += vaio_decode($i, '57');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found)
|
||||
{
|
||||
print("Vaio EEPROM not found. Please make sure that the eeprom module is loaded.\n");
|
||||
}
|
||||
182
Script/i2c-tools-3.1.0/eepromer/24cXX.c
Normal file
182
Script/i2c-tools-3.1.0/eepromer/24cXX.c
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/***************************************************************************
|
||||
copyright : (C) by 2002-2003 Stefano Barbato
|
||||
email : stefano@codesink.org
|
||||
|
||||
$Id: 24cXX.c 4230 2006-11-10 09:22:12Z khali $
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/fs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "24cXX.h"
|
||||
|
||||
static int i2c_write_1b(struct eeprom *e, __u8 buf)
|
||||
{
|
||||
int r;
|
||||
// we must simulate a plain I2C byte write with SMBus functions
|
||||
r = i2c_smbus_write_byte(e->fd, buf);
|
||||
if(r < 0)
|
||||
fprintf(stderr, "Error i2c_write_1b: %s\n", strerror(errno));
|
||||
usleep(10);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int i2c_write_2b(struct eeprom *e, __u8 buf[2])
|
||||
{
|
||||
int r;
|
||||
// we must simulate a plain I2C byte write with SMBus functions
|
||||
r = i2c_smbus_write_byte_data(e->fd, buf[0], buf[1]);
|
||||
if(r < 0)
|
||||
fprintf(stderr, "Error i2c_write_2b: %s\n", strerror(errno));
|
||||
usleep(10);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int i2c_write_3b(struct eeprom *e, __u8 buf[3])
|
||||
{
|
||||
int r;
|
||||
// we must simulate a plain I2C byte write with SMBus functions
|
||||
// the __u16 data field will be byte swapped by the SMBus protocol
|
||||
r = i2c_smbus_write_word_data(e->fd, buf[0], buf[2] << 8 | buf[1]);
|
||||
if(r < 0)
|
||||
fprintf(stderr, "Error i2c_write_3b: %s\n", strerror(errno));
|
||||
usleep(10);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_I2C_FUNC( var, label ) \
|
||||
do { if(0 == (var & label)) { \
|
||||
fprintf(stderr, "\nError: " \
|
||||
#label " function is required. Program halted.\n\n"); \
|
||||
exit(1); } \
|
||||
} while(0);
|
||||
|
||||
int eeprom_open(char *dev_fqn, int addr, int type, struct eeprom* e)
|
||||
{
|
||||
int fd, r;
|
||||
unsigned long funcs;
|
||||
e->fd = e->addr = 0;
|
||||
e->dev = 0;
|
||||
|
||||
fd = open(dev_fqn, O_RDWR);
|
||||
if(fd <= 0)
|
||||
return -1;
|
||||
|
||||
// get funcs list
|
||||
if((r = ioctl(fd, I2C_FUNCS, &funcs) < 0))
|
||||
return r;
|
||||
|
||||
|
||||
// check for req funcs
|
||||
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE );
|
||||
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE );
|
||||
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_BYTE_DATA );
|
||||
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_BYTE_DATA );
|
||||
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_READ_WORD_DATA );
|
||||
CHECK_I2C_FUNC( funcs, I2C_FUNC_SMBUS_WRITE_WORD_DATA );
|
||||
|
||||
// set working device
|
||||
if( ( r = ioctl(fd, I2C_SLAVE, addr)) < 0)
|
||||
return r;
|
||||
e->fd = fd;
|
||||
e->addr = addr;
|
||||
e->dev = dev_fqn;
|
||||
e->type = type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eeprom_close(struct eeprom *e)
|
||||
{
|
||||
close(e->fd);
|
||||
e->fd = -1;
|
||||
e->dev = 0;
|
||||
e->type = EEPROM_TYPE_UNKNOWN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int eeprom_24c32_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data)
|
||||
{
|
||||
__u8 buf[3] = { (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data };
|
||||
return i2c_write_3b(e, buf);
|
||||
}
|
||||
|
||||
|
||||
int eeprom_24c32_read_current_byte(struct eeprom* e)
|
||||
{
|
||||
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
|
||||
return i2c_smbus_read_byte(e->fd);
|
||||
}
|
||||
|
||||
int eeprom_24c32_read_byte(struct eeprom* e, __u16 mem_addr)
|
||||
{
|
||||
int r;
|
||||
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
|
||||
__u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff };
|
||||
r = i2c_write_2b(e, buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = i2c_smbus_read_byte(e->fd);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int eeprom_read_current_byte(struct eeprom* e)
|
||||
{
|
||||
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
|
||||
return i2c_smbus_read_byte(e->fd);
|
||||
}
|
||||
|
||||
int eeprom_read_byte(struct eeprom* e, __u16 mem_addr)
|
||||
{
|
||||
int r;
|
||||
ioctl(e->fd, BLKFLSBUF); // clear kernel read buffer
|
||||
if(e->type == EEPROM_TYPE_8BIT_ADDR)
|
||||
{
|
||||
__u8 buf = mem_addr & 0x0ff;
|
||||
r = i2c_write_1b(e, buf);
|
||||
} else if(e->type == EEPROM_TYPE_16BIT_ADDR) {
|
||||
__u8 buf[2] = { (mem_addr >> 8) & 0x0ff, mem_addr & 0x0ff };
|
||||
r = i2c_write_2b(e, buf);
|
||||
} else {
|
||||
fprintf(stderr, "ERR: unknown eeprom type\n");
|
||||
return -1;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = i2c_smbus_read_byte(e->fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data)
|
||||
{
|
||||
if(e->type == EEPROM_TYPE_8BIT_ADDR) {
|
||||
__u8 buf[2] = { mem_addr & 0x00ff, data };
|
||||
return i2c_write_2b(e, buf);
|
||||
} else if(e->type == EEPROM_TYPE_16BIT_ADDR) {
|
||||
__u8 buf[3] =
|
||||
{ (mem_addr >> 8) & 0x00ff, mem_addr & 0x00ff, data };
|
||||
return i2c_write_3b(e, buf);
|
||||
} else {
|
||||
fprintf(stderr, "ERR: unknown eeprom type\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
58
Script/i2c-tools-3.1.0/eepromer/24cXX.h
Normal file
58
Script/i2c-tools-3.1.0/eepromer/24cXX.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/***************************************************************************
|
||||
copyright : (C) by 2002-2003 Stefano Barbato
|
||||
email : stefano@codesink.org
|
||||
|
||||
$Id: 24cXX.h 4495 2007-06-27 12:57:50Z khali $
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef _24CXX_H_
|
||||
#define _24CXX_H_
|
||||
#include <linux/i2c-dev.h>
|
||||
|
||||
#define EEPROM_TYPE_UNKNOWN 0
|
||||
#define EEPROM_TYPE_8BIT_ADDR 1
|
||||
#define EEPROM_TYPE_16BIT_ADDR 2
|
||||
|
||||
struct eeprom
|
||||
{
|
||||
char *dev; // device file i.e. /dev/i2c-N
|
||||
int addr; // i2c address
|
||||
int fd; // file descriptor
|
||||
int type; // eeprom type
|
||||
};
|
||||
|
||||
/*
|
||||
* opens the eeprom device at [dev_fqn] (i.e. /dev/i2c-N) whose address is
|
||||
* [addr] and set the eeprom_24c32 [e]
|
||||
*/
|
||||
int eeprom_open(char *dev_fqn, int addr, int type, struct eeprom*);
|
||||
/*
|
||||
* closees the eeprom device [e]
|
||||
*/
|
||||
int eeprom_close(struct eeprom *e);
|
||||
/*
|
||||
* read and returns the eeprom byte at memory address [mem_addr]
|
||||
* Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address)
|
||||
*/
|
||||
int eeprom_read_byte(struct eeprom* e, __u16 mem_addr);
|
||||
/*
|
||||
* read the current byte
|
||||
* Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address)
|
||||
*/
|
||||
int eeprom_read_current_byte(struct eeprom *e);
|
||||
/*
|
||||
* writes [data] at memory address [mem_addr]
|
||||
* Note: eeprom must have been selected by ioctl(fd,I2C_SLAVE,address)
|
||||
*/
|
||||
int eeprom_write_byte(struct eeprom *e, __u16 mem_addr, __u8 data);
|
||||
|
||||
#endif
|
||||
|
||||
14
Script/i2c-tools-3.1.0/eepromer/Makefile
Normal file
14
Script/i2c-tools-3.1.0/eepromer/Makefile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#eepromer Makefile
|
||||
|
||||
CFLAGS = -O2 -I../include -Wall
|
||||
|
||||
all: eepromer eeprom eeprog
|
||||
|
||||
eepromer: eepromer.o
|
||||
|
||||
eeprom: eeprom.o
|
||||
|
||||
eeprog: eeprog.o 24cXX.o
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.o eepromer eeprom eeprog
|
||||
31
Script/i2c-tools-3.1.0/eepromer/README
Normal file
31
Script/i2c-tools-3.1.0/eepromer/README
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
These programs are used to read and write eeproms.
|
||||
|
||||
Use eeprom for small eeproms with one-byte addresses:
|
||||
24C01, 24C01A, 24C02, 24C04, 24C08, and 24C16
|
||||
It works only on true i2c bus adapters.
|
||||
See README.eeprom for details.
|
||||
|
||||
Use eepromer for large eeproms with two-byte addresses:
|
||||
24C32, 24C64, 24C128, 24C256, and 24C512
|
||||
It works only on true i2c bus adapters.
|
||||
See README.eepromer for details.
|
||||
|
||||
Use eeprog for either small or large eeproms.
|
||||
Use the -16 switch for large eeproms.
|
||||
It works on both i2c and smbus bus adapters.
|
||||
See README.eeprog for details.
|
||||
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!! !
|
||||
!!! These programs should only be used on external busses such as i2c-pport !
|
||||
!!! unless you REALLY know what you are doing. !
|
||||
!!! !
|
||||
!!! Your computer probably contains eeproms for saving data vital to its !
|
||||
!!! operation. If you are not careful you might overwrite this data with !
|
||||
!!! this program and your computer may no longer boot! !
|
||||
!!! !
|
||||
!!! An example are the EEPROMS on your SDRAM DIMMs, your computer may no !
|
||||
!!! longer detect the RAM module rendering it essentially USELESS! !
|
||||
!!! !
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
12
Script/i2c-tools-3.1.0/eepromer/README.eeprog
Normal file
12
Script/i2c-tools-3.1.0/eepromer/README.eeprog
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Important! See the README file for important warnings.
|
||||
|
||||
eeprog reads and writes 24Cxx EEPROMs connected to I2C serial bus.
|
||||
|
||||
It uses the SMBus protocol used by most of the recent chipsets. Don't forget to load
|
||||
your i2c chipset and the i2c-dev drivers.
|
||||
|
||||
Use -16 switch for EEPROM larger then 24C16 (16 bit addressing mode).
|
||||
|
||||
Again, it's really important that you read the README file.
|
||||
|
||||
Type "make" to compile.
|
||||
85
Script/i2c-tools-3.1.0/eepromer/README.eeprom
Normal file
85
Script/i2c-tools-3.1.0/eepromer/README.eeprom
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
You can use this program to read/write to i2c-eeproms
|
||||
like the popular 24C16, 24C08, 24C04,.. In contrast to eeprommer
|
||||
which supports 24C256-type eeproms 24C16ss use 1-byte addresses!
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!! !
|
||||
!!! This program should only be used on external busses such as i2c-pport. !
|
||||
!!! !
|
||||
!!! Your computer may contain i2c-eeproms for saving data vital to its !
|
||||
!!! operation. If you are not careful you might overwrite this data with !
|
||||
!!! this program and your computer may no longer boot! !
|
||||
!!! !
|
||||
!!! An example are the EEPROMS on your SDRAM DIMMs, your computer may no !
|
||||
!!! longer detect the RAM module rendering it essentially USELESS! !
|
||||
!!! !
|
||||
!!! IBM Thinkpads are said to store their configuration data in a eeprom, !
|
||||
!!! if you manage to overwrite this eeprom you will have to send your !
|
||||
!!! computer to the manufacturer for a costly repair! !
|
||||
!!! !
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
It has several options:
|
||||
|
||||
-d devicenode
|
||||
|
||||
set this to the device-node of the i2c-bus
|
||||
you want to use like /dev/i2c-0.
|
||||
Use /dev/i2c-1 for the second bus, i2c-2 for the third...
|
||||
|
||||
The default /dev/i2c-0 should work most of the time.
|
||||
|
||||
-a address
|
||||
|
||||
set this to the device-address of your
|
||||
eeprom. For a 24C16 the address is hardcoded to
|
||||
0x50, which is -you guessed it- the default.
|
||||
|
||||
For a 24C08 and smaller types you can choose which
|
||||
addresses they occupy by forcing the address-pins
|
||||
of the chip to High or Low so here the address may differ.
|
||||
|
||||
-p number_of_pages
|
||||
|
||||
set this to the number of pages you want to read
|
||||
from or write to the eeprom. The 24C16 maps it's
|
||||
pages to consecutive addresses on the i2c-bus so
|
||||
we will try to read 256 bytes from every i2c
|
||||
address between 'address' (inclusive) and
|
||||
'address + number_of_pages' (exclusive)...
|
||||
|
||||
A 24C16 has 8 pages so that's the default for this
|
||||
parameter.
|
||||
|
||||
-f filename
|
||||
|
||||
read data from this file (when writing to eeprom) or
|
||||
write data to this file (when reading from eeprom).
|
||||
|
||||
When reading a file that's smaller than the
|
||||
eeprom's storage size we will pad the eeprom
|
||||
with zeroes.
|
||||
|
||||
If no file is given we will just read the
|
||||
eeprom (while in read-mode) and test it's presence
|
||||
this way. In write-mode we will just write zeroes
|
||||
to the eeprom.
|
||||
|
||||
-w When '-w' is present we will *write* to the eeprom.
|
||||
If you do not specify '-w' we will read the contents
|
||||
of the eeprom.
|
||||
|
||||
-y This flag will suppress the warning when you write to the
|
||||
eeprom. You will not be required to enter 'yes' so be careful
|
||||
when using this switch!
|
||||
|
||||
|
||||
I wrote that program to clear a 24C16 eeprom that sit's in my crappy
|
||||
satellite receiver because sometimes its Z80 processor likes to
|
||||
write garbage to it and then crash....
|
||||
|
||||
No further testing besides writing a long series of "The quick brown
|
||||
fox jumps over the lazy dog!" and reading it back has been done so
|
||||
of course this comes without any warranty.
|
||||
|
||||
Chris <chris@hedonism.cx>
|
||||
27
Script/i2c-tools-3.1.0/eepromer/README.eepromer
Normal file
27
Script/i2c-tools-3.1.0/eepromer/README.eepromer
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Simple program for storing data to I2C EEPROM.
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
The EEPROM must be a large EEPROM which uses a 2-byte address
|
||||
field (24C32 or larger). It will NOT WORK on small EEPROMs
|
||||
(24C01 - 24C16) such as those used on SDRAM DIMMs.
|
||||
|
||||
Tested only on 24C256.
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
This program is intended for use on eeproms using external busses such as
|
||||
i2c-pport.
|
||||
Do not use this on your SDRAM DIMM EEPROMS, it won't work!!!!!!!!!
|
||||
Doing so will render your SDRAM USELESS and leave your system UNBOOTABLE!!!
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!Warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
Options:
|
||||
-r read
|
||||
-w write
|
||||
-e erase
|
||||
-p print "super block of EEPROM" (date and size stored data)
|
||||
|
||||
Daniel Smolik
|
||||
marvin@sitour.cz
|
||||
283
Script/i2c-tools-3.1.0/eepromer/eeprog.c
Normal file
283
Script/i2c-tools-3.1.0/eepromer/eeprog.c
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/***************************************************************************
|
||||
copyright : (C) by 2002-2003 Stefano Barbato
|
||||
email : stefano@codesink.org
|
||||
|
||||
$Id: eeprog.c 5122 2008-02-18 09:22:21Z khali $
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "24cXX.h"
|
||||
|
||||
#define VERSION "0.7.5"
|
||||
|
||||
#define ENV_DEV "EEPROG_DEV"
|
||||
#define ENV_I2C_ADDR "EEPROG_I2C_ADDR"
|
||||
|
||||
int g_quiet;
|
||||
|
||||
#define usage_if(a) do { do_usage_if( a , __LINE__); } while(0);
|
||||
void do_usage_if(int b, int line)
|
||||
{
|
||||
static const char *eeprog_usage =
|
||||
"eeprog " VERSION ", a 24Cxx EEPROM reader/writer\n"
|
||||
"Copyright (c) 2003 by Stefano Barbato - All rights reserved.\n"
|
||||
"Usage: eeprog [-fqxdh] [-16|-8] [ -r addr[:count] | -w addr ] /dev/i2c-N i2c-address\n"
|
||||
"\n"
|
||||
" Address modes:\n"
|
||||
" -8 Use 8bit address mode for 24c0x...24C16 [default]\n"
|
||||
" -16 Use 16bit address mode for 24c32...24C256\n"
|
||||
" Actions:\n"
|
||||
" -r addr[:count] Read [count] (1 if omitted) bytes from [addr]\n"
|
||||
" and print them to the standard output\n"
|
||||
" -w addr Write input (stdin) at address [addr] of the EEPROM\n"
|
||||
" -h Print this help\n"
|
||||
" Options:\n"
|
||||
" -x Set hex output mode\n"
|
||||
" -d Dummy mode, display what *would* have been done\n"
|
||||
" -f Disable warnings and don't ask confirmation\n"
|
||||
" -q Quiet mode\n"
|
||||
"\n"
|
||||
"The following environment variables could be set instead of the command\n"
|
||||
"line arguments:\n"
|
||||
" EEPROG_DEV device name(/dev/i2c-N)\n"
|
||||
" EEPROG_I2C_ADDR i2c-address\n"
|
||||
"\n"
|
||||
" Examples\n"
|
||||
" 1- read 64 bytes from the EEPROM at address 0x54 on bus 0 starting\n"
|
||||
" at address 123 (decimal)\n"
|
||||
" eeprog /dev/i2c-0 0x54 -r 123:64\n"
|
||||
" 2- prints the hex codes of the first 32 bytes read from bus 1\n"
|
||||
" at address 0x22\n"
|
||||
" eeprog /dev/i2c-1 0x51 -x -r 0x22:0x20\n"
|
||||
" 3- write the current timestamp at address 0x200 of the EEPROM on\n"
|
||||
" bus 0 at address 0x33\n"
|
||||
" date | eeprog /dev/i2c-0 0x33 -w 0x200\n";
|
||||
|
||||
if(!b)
|
||||
return;
|
||||
fprintf(stderr, "%s\n[line %d]\n", eeprog_usage, line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
#define die_if(a, msg) do { do_die_if( a , msg, __LINE__); } while(0);
|
||||
void do_die_if(int b, char* msg, int line)
|
||||
{
|
||||
if(!b)
|
||||
return;
|
||||
fprintf(stderr, "Error at line %d: %s\n", line, msg);
|
||||
//fprintf(stderr, " sysmsg: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define print_info(args...) do { if(!g_quiet) fprintf(stderr, args); } while(0);
|
||||
|
||||
void parse_arg(char *arg, int* paddr, int *psize)
|
||||
{
|
||||
char *end;
|
||||
*paddr = strtoul(arg, &end, 0);
|
||||
if(*end == ':')
|
||||
*psize = strtoul(++end, 0, 0);
|
||||
}
|
||||
|
||||
int confirm_action()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"____________________________WARNING____________________________\n"
|
||||
"Erroneously writing to a system EEPROM (like DIMM SPD modules)\n"
|
||||
"can break your system. It will NOT boot anymore so you'll not\n"
|
||||
"be able to fix it.\n"
|
||||
"\n"
|
||||
"Reading from 8bit EEPROMs (like that in your DIMM) without using\n"
|
||||
"the -8 switch can also UNEXPECTEDLY write to them, so be sure to\n"
|
||||
"use the -8 command param when required.\n"
|
||||
"\n"
|
||||
"Use -f to disable this warning message\n"
|
||||
"\n"
|
||||
"Press ENTER to continue or hit CTRL-C to exit\n"
|
||||
"\n"
|
||||
);
|
||||
getchar();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int read_from_eeprom(struct eeprom *e, int addr, int size, int hex)
|
||||
{
|
||||
|
||||
int ch, i;
|
||||
// hex print out
|
||||
die_if((ch = eeprom_read_byte(e, addr)) < 0, "read error");
|
||||
i = 1;
|
||||
if(hex)
|
||||
printf("\n %.4x| %.2x ", addr, ch);
|
||||
else
|
||||
putchar(ch);
|
||||
while(--size)
|
||||
{
|
||||
die_if((ch = eeprom_read_current_byte(e)) < 0, "read error");
|
||||
if(hex)
|
||||
{
|
||||
addr++;
|
||||
if( (i % 16) == 0 )
|
||||
printf("\n %.4x| ", addr);
|
||||
else if( (i % 8) == 0 )
|
||||
printf(" ");
|
||||
i++;
|
||||
printf("%.2x ", ch);
|
||||
} else {
|
||||
putchar(ch);
|
||||
}
|
||||
}
|
||||
if(hex)
|
||||
printf("\n\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_to_eeprom(struct eeprom *e, int addr)
|
||||
{
|
||||
int c;
|
||||
while((c = getchar()) != EOF)
|
||||
{
|
||||
print_info(".");
|
||||
fflush(stdout);
|
||||
die_if(eeprom_write_byte(e, addr++, c), "write error");
|
||||
}
|
||||
print_info("\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
struct eeprom e;
|
||||
int ret, op, i2c_addr, memaddr, size, want_hex, dummy, force, sixteen;
|
||||
char *device, *arg = 0, *i2c_addr_s;
|
||||
struct stat st;
|
||||
int eeprom_type = 0;
|
||||
|
||||
op = want_hex = dummy = force = sixteen = 0;
|
||||
g_quiet = 0;
|
||||
|
||||
while((ret = getopt(argc, argv, "1:8fr:qhw:xd")) != -1)
|
||||
{
|
||||
switch(ret)
|
||||
{
|
||||
case '1':
|
||||
usage_if(*optarg != '6' || strlen(optarg) != 1);
|
||||
die_if(eeprom_type, "EEPROM type switch (-8 or -16) used twice");
|
||||
eeprom_type = EEPROM_TYPE_16BIT_ADDR;
|
||||
break;
|
||||
case 'x':
|
||||
want_hex++;
|
||||
break;
|
||||
case 'd':
|
||||
dummy++;
|
||||
break;
|
||||
case '8':
|
||||
die_if(eeprom_type, "EEPROM type switch (-8 or -16) used twice");
|
||||
eeprom_type = EEPROM_TYPE_8BIT_ADDR;
|
||||
break;
|
||||
case 'f':
|
||||
force++;
|
||||
break;
|
||||
case 'q':
|
||||
g_quiet++;
|
||||
break;
|
||||
case 'h':
|
||||
usage_if(1);
|
||||
break;
|
||||
default:
|
||||
die_if(op != 0, "Both read and write requested");
|
||||
arg = optarg;
|
||||
op = ret;
|
||||
}
|
||||
}
|
||||
if(!eeprom_type)
|
||||
eeprom_type = EEPROM_TYPE_8BIT_ADDR; // default
|
||||
|
||||
usage_if(op == 0); // no switches
|
||||
// set device and i2c_addr reading from cmdline or env
|
||||
device = i2c_addr_s = 0;
|
||||
switch(argc - optind)
|
||||
{
|
||||
case 0:
|
||||
device = getenv(ENV_DEV);
|
||||
i2c_addr_s = getenv(ENV_I2C_ADDR);
|
||||
break;
|
||||
case 1:
|
||||
if(stat(argv[optind], &st) != -1)
|
||||
{
|
||||
device = argv[optind];
|
||||
i2c_addr_s = getenv(ENV_I2C_ADDR);
|
||||
} else {
|
||||
device = getenv(ENV_DEV);
|
||||
i2c_addr_s = argv[optind];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
device = argv[optind++];
|
||||
i2c_addr_s = argv[optind];
|
||||
break;
|
||||
default:
|
||||
usage_if(1);
|
||||
}
|
||||
usage_if(!device || !i2c_addr_s);
|
||||
i2c_addr = strtoul(i2c_addr_s, 0, 0);
|
||||
|
||||
print_info("eeprog %s, a 24Cxx EEPROM reader/writer\n", VERSION);
|
||||
print_info("Copyright (c) 2003 by Stefano Barbato - All rights reserved.\n");
|
||||
print_info(" Bus: %s, Address: 0x%x, Mode: %dbit\n",
|
||||
device, i2c_addr,
|
||||
(eeprom_type == EEPROM_TYPE_8BIT_ADDR ? 8 : 16) );
|
||||
if(dummy)
|
||||
{
|
||||
fprintf(stderr, "Dummy mode selected, nothing done.\n");
|
||||
return 0;
|
||||
}
|
||||
die_if(eeprom_open(device, i2c_addr, eeprom_type, &e) < 0,
|
||||
"unable to open eeprom device file (check that the file exists and that it's readable)");
|
||||
switch(op)
|
||||
{
|
||||
case 'r':
|
||||
if(force == 0)
|
||||
confirm_action();
|
||||
size = 1; // default
|
||||
parse_arg(arg, &memaddr, &size);
|
||||
print_info(" Reading %d bytes from 0x%x\n", size, memaddr);
|
||||
read_from_eeprom(&e, memaddr, size, want_hex);
|
||||
break;
|
||||
case 'w':
|
||||
if(force == 0)
|
||||
confirm_action();
|
||||
parse_arg(arg, &memaddr, &size);
|
||||
print_info(" Writing stdin starting at address 0x%x\n",
|
||||
memaddr);
|
||||
write_to_eeprom(&e, memaddr);
|
||||
break;
|
||||
default:
|
||||
usage_if(1);
|
||||
exit(1);
|
||||
}
|
||||
eeprom_close(&e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
297
Script/i2c-tools-3.1.0/eepromer/eeprom.c
Normal file
297
Script/i2c-tools-3.1.0/eepromer/eeprom.c
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
This program is hereby placed into the public domain.
|
||||
Of course the program is provided without warranty of any kind.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
|
||||
/*
|
||||
this program can read 24C16 (and probably smaller ones, too)
|
||||
I wrote it as a quick and dirty hack because my satellite receiver
|
||||
hung again... so I had to reprogram the eeprom where is stores it's
|
||||
settings.
|
||||
*/
|
||||
|
||||
#define DEFAULT_I2C_BUS "/dev/i2c-0"
|
||||
#define DEFAULT_EEPROM_ADDR 0x50 /* the 24C16 sits on i2c address 0x50 */
|
||||
#define DEFAULT_NUM_PAGES 8 /* we default to a 24C16 eeprom which has 8 pages */
|
||||
#define BYTES_PER_PAGE 256 /* one eeprom page is 256 byte */
|
||||
#define MAX_BYTES 8 /* max number of bytes to write in one chunk */
|
||||
/* ... note: 24C02 and 24C01 only allow 8 bytes to be written in one chunk. *
|
||||
* if you are going to write 24C04,8,16 you can change this to 16 */
|
||||
|
||||
/* write len bytes (stored in buf) to eeprom at address addr, page-offset offset */
|
||||
/* if len=0 (buf may be NULL in this case) you can reposition the eeprom's read-pointer */
|
||||
/* return 0 on success, -1 on failure */
|
||||
int eeprom_write(int fd,
|
||||
unsigned int addr,
|
||||
unsigned int offset,
|
||||
unsigned char *buf,
|
||||
unsigned char len
|
||||
){
|
||||
struct i2c_rdwr_ioctl_data msg_rdwr;
|
||||
struct i2c_msg i2cmsg;
|
||||
int i;
|
||||
char _buf[MAX_BYTES + 1];
|
||||
|
||||
if(len>MAX_BYTES){
|
||||
fprintf(stderr,"I can only write MAX_BYTES bytes at a time!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(len+offset >256){
|
||||
fprintf(stderr,"Sorry, len(%d)+offset(%d) > 256 (page boundary)\n",
|
||||
len,offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_buf[0]=offset; /* _buf[0] is the offset into the eeprom page! */
|
||||
for(i=0;i<len;i++) /* copy buf[0..n] -> _buf[1..n+1] */
|
||||
_buf[1+i]=buf[i];
|
||||
|
||||
msg_rdwr.msgs = &i2cmsg;
|
||||
msg_rdwr.nmsgs = 1;
|
||||
|
||||
i2cmsg.addr = addr;
|
||||
i2cmsg.flags = 0;
|
||||
i2cmsg.len = 1+len;
|
||||
i2cmsg.buf = _buf;
|
||||
|
||||
if((i=ioctl(fd,I2C_RDWR,&msg_rdwr))<0){
|
||||
perror("ioctl()");
|
||||
fprintf(stderr,"ioctl returned %d\n",i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(len>0)
|
||||
fprintf(stderr,"Wrote %d bytes to eeprom at 0x%02x, offset %08x\n",
|
||||
len,addr,offset);
|
||||
else
|
||||
fprintf(stderr,"Positioned pointer in eeprom at 0x%02x to offset %08x\n",
|
||||
addr,offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read len bytes stored in eeprom at address addr, offset offset in array buf */
|
||||
/* return -1 on error, 0 on success */
|
||||
int eeprom_read(int fd,
|
||||
unsigned int addr,
|
||||
unsigned int offset,
|
||||
unsigned char *buf,
|
||||
unsigned char len
|
||||
){
|
||||
struct i2c_rdwr_ioctl_data msg_rdwr;
|
||||
struct i2c_msg i2cmsg;
|
||||
int i;
|
||||
|
||||
if(len>MAX_BYTES){
|
||||
fprintf(stderr,"I can only write MAX_BYTES bytes at a time!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(eeprom_write(fd,addr,offset,NULL,0)<0)
|
||||
return -1;
|
||||
|
||||
msg_rdwr.msgs = &i2cmsg;
|
||||
msg_rdwr.nmsgs = 1;
|
||||
|
||||
i2cmsg.addr = addr;
|
||||
i2cmsg.flags = I2C_M_RD;
|
||||
i2cmsg.len = len;
|
||||
i2cmsg.buf = buf;
|
||||
|
||||
if((i=ioctl(fd,I2C_RDWR,&msg_rdwr))<0){
|
||||
perror("ioctl()");
|
||||
fprintf(stderr,"ioctl returned %d\n",i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Read %d bytes from eeprom at 0x%02x, offset %08x\n",
|
||||
len,addr,offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int i,j;
|
||||
|
||||
/* filedescriptor and name of device */
|
||||
int d;
|
||||
char *dn=DEFAULT_I2C_BUS;
|
||||
|
||||
/* filedescriptor and name of data file */
|
||||
int f=-1;
|
||||
char *fn=NULL;
|
||||
|
||||
unsigned int addr=DEFAULT_EEPROM_ADDR;
|
||||
int rwmode=0;
|
||||
int pages=DEFAULT_NUM_PAGES;
|
||||
|
||||
int force=0; /* suppress warning on write! */
|
||||
|
||||
while((i=getopt(argc,argv,"d:a:p:wyf:h"))>=0){
|
||||
switch(i){
|
||||
case 'h':
|
||||
fprintf(stderr,"%s [-d dev] [-a adr] [-p pgs] [-w] [-y] [-f file]\n",argv[0]);
|
||||
fprintf(stderr,"\tdev: device, e.g. /dev/i2c-0 (def)\n");
|
||||
fprintf(stderr,"\tadr: base address of eeprom, eg 0xA0 (def)\n");
|
||||
fprintf(stderr,"\tpgs: number of pages to read, eg 8 (def)\n");
|
||||
fprintf(stderr,"\t-w : write to eeprom (default is reading!)\n");
|
||||
fprintf(stderr,"\t-y : suppress warning when writing (default is to warn!)\n");
|
||||
fprintf(stderr,"\t-f file: copy eeprom contents to/from file\n");
|
||||
fprintf(stderr,"\t (default for read is test only; for write is all zeros)\n");
|
||||
fprintf(stderr,"Note on pages/addresses:\n");
|
||||
fprintf(stderr,"\teeproms with more than 256 byte appear as if they\n");
|
||||
fprintf(stderr,"\twere several eeproms with consecutive addresses on the bus\n");
|
||||
fprintf(stderr,"\tso we might as well address several separate eeproms with\n");
|
||||
fprintf(stderr,"\tincreasing addresses....\n\n");
|
||||
exit(1);
|
||||
break;
|
||||
case 'd':
|
||||
dn=optarg;
|
||||
break;
|
||||
case 'a':
|
||||
if(sscanf(optarg,"0x%x",&addr)!=1){
|
||||
fprintf(stderr,"Cannot parse '%s' as addrs., example: 0xa0\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if(sscanf(optarg,"%d",&pages)!=1){
|
||||
fprintf(stderr,"Cannot parse '%s' as number of pages, example: 8\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
rwmode++;
|
||||
break;
|
||||
case 'f':
|
||||
fn=optarg;
|
||||
break;
|
||||
case 'y':
|
||||
force++;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fprintf(stderr,"base-address of eeproms : 0x%02x\n",addr);
|
||||
fprintf(stderr,"number of pages to read : %d (0x%02x .. 0x%02x)\n",
|
||||
pages,addr,addr+pages-1);
|
||||
|
||||
if(fn){
|
||||
if(!rwmode) /* if we are reading, *WRITE* to file */
|
||||
f=open(fn,O_WRONLY|O_CREAT,0666);
|
||||
else /* if we are writing to eeprom, *READ* from file */
|
||||
f=open(fn,O_RDONLY);
|
||||
if(f<0){
|
||||
fprintf(stderr,"Could not open data-file %s for reading or writing\n",fn);
|
||||
perror(fn);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr,"file opened for %7s : %s\n",rwmode?"reading":"writing",fn);
|
||||
fprintf(stderr," on filedescriptor : %d\n",f);
|
||||
}
|
||||
|
||||
if((d=open(dn,O_RDWR))<0){
|
||||
fprintf(stderr,"Could not open i2c at %s\n",dn);
|
||||
perror(dn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr,"i2c-devicenode is : %s\n",dn);
|
||||
fprintf(stderr," on filedescriptor : %d\n\n",d);
|
||||
|
||||
/***
|
||||
*** I'm not the one to blame of you screw your computer!
|
||||
***/
|
||||
if(rwmode && ! force){
|
||||
unsigned char warnbuf[4];
|
||||
fprintf(stderr,"**WARNING**\n");
|
||||
fprintf(stderr," - \tYou have chosen to WRITE to this eeprom.\n");
|
||||
fprintf(stderr,"\tMake sure that this tiny chip is *NOT* vital to the\n");
|
||||
fprintf(stderr,"\toperation of your computer as you can easily corrupt\n");
|
||||
fprintf(stderr,"\tthe configuration memory of your SDRAM-memory-module,\n");
|
||||
fprintf(stderr,"\tyour IBM ThinkPad or whatnot...! Fixing these errors can be\n");
|
||||
fprintf(stderr,"\ta time-consuming and very costly process!\n\n");
|
||||
fprintf(stderr,"Things to consider:\n");
|
||||
fprintf(stderr," - \tYou can have more than one i2c-bus, check in /proc/bus/i2c\n");
|
||||
fprintf(stderr,"\tand specify the correct one with -d\n");
|
||||
fprintf(stderr,"\tright now you have chosen to use '%s'\n",dn);
|
||||
fprintf(stderr," - \tA eeprom can occupy several i2c-addresses (one per page)\n");
|
||||
fprintf(stderr,"\tso please make sure that there is no vital eeprom in your computer\n");
|
||||
fprintf(stderr,"\tsitting at addresses between 0x%02x and 0x%02x\n",addr,addr+pages-1);
|
||||
|
||||
fprintf(stderr,"Enter 'yes' to continue:");
|
||||
fflush(stderr);
|
||||
if(!fgets(warnbuf,sizeof(warnbuf),stdin)){
|
||||
fprintf(stderr,"\nCould not read confirmation from stdin!\n");
|
||||
exit(1);
|
||||
}
|
||||
if(strncmp(warnbuf,"yes",3)){
|
||||
fprintf(stderr,"\n** ABORTING WRITE! **, you did not answer 'yes'\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<pages;i++){
|
||||
unsigned char buf[BYTES_PER_PAGE];
|
||||
|
||||
if(rwmode){
|
||||
|
||||
if(f>=0){
|
||||
j=read(f,buf,sizeof(buf));
|
||||
if(j<0){
|
||||
fprintf(stderr,"Cannot read from file '%s'\n",fn);
|
||||
perror(fn);
|
||||
exit(1);
|
||||
}
|
||||
if(j!=sizeof(buf)){
|
||||
fprintf(stderr,"File '%s' is too small, padding eeprom with zeroes\n",fn);
|
||||
while(j<sizeof(buf))
|
||||
buf[j++]=0;
|
||||
}
|
||||
} else {
|
||||
for(j=0;j<sizeof(buf);j++)
|
||||
buf[j]=0;
|
||||
}
|
||||
for(j=0;j<(BYTES_PER_PAGE/MAX_BYTES);j++)
|
||||
if(eeprom_write(d,addr+i,j*MAX_BYTES,buf+(j*MAX_BYTES),MAX_BYTES)<0)
|
||||
exit(1);
|
||||
} else {
|
||||
for(j=0;j<(BYTES_PER_PAGE/MAX_BYTES);j++)
|
||||
if(eeprom_read(d,addr+i,j*MAX_BYTES,buf+(j*MAX_BYTES),MAX_BYTES)<0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if(!rwmode && f>=0){
|
||||
j=write(f,buf,sizeof(buf));
|
||||
if(j!=sizeof(buf)){
|
||||
fprintf(stderr,"Cannot write to file '%s'\n",fn);
|
||||
perror(fn);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(f>=0)
|
||||
close(f);
|
||||
|
||||
close(d);
|
||||
|
||||
exit(0);
|
||||
|
||||
}
|
||||
721
Script/i2c-tools-3.1.0/eepromer/eepromer.c
Normal file
721
Script/i2c-tools-3.1.0/eepromer/eepromer.c
Normal file
|
|
@ -0,0 +1,721 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
|
||||
|
||||
#define MAX_BLK_SIZE 64
|
||||
#define EEPROM_SIZE 32768
|
||||
#define READ 1
|
||||
#define WRITE 0
|
||||
#define ERASE 2
|
||||
#define PHEADER 3
|
||||
#define VER "eepromer v 0.4 (c) Daniel Smolik 2001\n"
|
||||
#define HEAD_SIZE sizeof(struct mini_inode)
|
||||
#define START_ADDR 0
|
||||
#define FORCE 1
|
||||
/*
|
||||
To disable startup warning #undef WARNINC
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#define WARNINC
|
||||
|
||||
|
||||
int block_write(int file,int dev_addr,int eeprom_addr,unsigned char *buf,int lenght);int block_write(int file,int dev_addr,int eeprom_addr,unsigned char *buf,int lenght);
|
||||
int block_read(int file,int dev_addr,int eeprom_addr,unsigned char *buf);
|
||||
|
||||
/* block_read read block 64 bytes length and returns actual length of data*/
|
||||
void help(void);
|
||||
int init(char *device,int addr);
|
||||
int content_write(int file, int addr);
|
||||
int content_read(int file, int addr);
|
||||
int inode_write(int file, int dev_addr, int lenght);
|
||||
int inode_read(int file, int dev_addr, void *p_inode);
|
||||
void pheader(int file, int addr);
|
||||
void erase(int file,int addr,int eeprom_size);
|
||||
void made_address(int addr,unsigned char *buf);
|
||||
void warn(void);
|
||||
void bar(void);
|
||||
|
||||
|
||||
static int stav=0;
|
||||
|
||||
|
||||
|
||||
static struct mini_inode {
|
||||
|
||||
time_t timestamp;
|
||||
int data_len;
|
||||
char data[56];
|
||||
|
||||
} m_ind,*p_ind;
|
||||
|
||||
|
||||
|
||||
void help(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
char s[100];
|
||||
|
||||
fprintf(stderr,"Syntax: eepromer [-r|-w|-e|-p] -f /dev/i2c-X ADDRESS \n\n");
|
||||
fprintf(stderr," ADDRESS is address of i2c device eg. 0x51\n");
|
||||
|
||||
if((fptr = fopen("/proc/bus/i2c", "r"))) {
|
||||
fprintf(stderr," Installed I2C busses:\n");
|
||||
while(fgets(s, 100, fptr))
|
||||
fprintf(stderr, " %s", s);
|
||||
fclose(fptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
int i, file, addr;
|
||||
int action; //in this variable will be (-r,-w,-e)
|
||||
char device[45];
|
||||
int force;
|
||||
|
||||
p_ind=&m_ind;
|
||||
force=0;
|
||||
|
||||
|
||||
|
||||
|
||||
for(i=1; i < argc;i++){
|
||||
|
||||
|
||||
if(!strcmp("-r",argv[i])) {
|
||||
action=READ;
|
||||
break;
|
||||
}
|
||||
if(!strcmp("-e",argv[i])) {
|
||||
action=ERASE;
|
||||
break;
|
||||
}
|
||||
if(!strcmp("-w",argv[i])) {
|
||||
action=WRITE;
|
||||
break;
|
||||
}
|
||||
if(!strcmp("-p",argv[i])) {
|
||||
action=PHEADER;
|
||||
break;
|
||||
}
|
||||
if(!strcmp("-force",argv[i])) {
|
||||
force=FORCE;
|
||||
break;
|
||||
}
|
||||
if(!strcmp("-v",argv[i])) {
|
||||
fprintf(stderr,VER);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
||||
fprintf(stderr,"Error: No action specified !\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef WARNINC
|
||||
|
||||
if(force!=FORCE) warn();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if(argc < 5) {
|
||||
fprintf(stderr,"Error: No i2c address specified !\n");
|
||||
help();
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
for(i=1; i < argc;i++){
|
||||
|
||||
|
||||
if(!strcmp("-f",argv[i])) {
|
||||
strcpy(device,argv[i+1]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!strlen(device)) {
|
||||
|
||||
fprintf(stderr,"Error: No device specified !\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if(! (addr=strtol(argv[4],NULL,16))) {
|
||||
|
||||
fprintf(stderr,"Error: Bad device address !\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(! (file=init(device,addr))){
|
||||
|
||||
fprintf(stderr,"Error: Init failed !\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
switch(action){
|
||||
|
||||
case READ:
|
||||
content_read(file,addr);
|
||||
break;
|
||||
|
||||
case WRITE:
|
||||
content_write(file,addr);
|
||||
break;
|
||||
|
||||
case ERASE: erase(file,addr,EEPROM_SIZE);
|
||||
break;
|
||||
case PHEADER: pheader(file,addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"Internal error!\n");
|
||||
exit(1); break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
close(file);
|
||||
exit(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Low level function */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int block_write(int file,int dev_addr,int eeprom_addr,unsigned char *buf,int lenght){
|
||||
|
||||
unsigned char buff[2];
|
||||
struct i2c_msg msg[2];
|
||||
|
||||
struct i2c_ioctl_rdwr_data {
|
||||
|
||||
struct i2c_msg *msgs; /* ptr to array of simple messages */
|
||||
int nmsgs; /* number of messages to exchange */
|
||||
} msgst;
|
||||
|
||||
|
||||
|
||||
if ( lenght > (MAX_BLK_SIZE) ) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: Block too large:\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
//bar();
|
||||
|
||||
made_address(eeprom_addr,buff);
|
||||
|
||||
|
||||
msg[0].addr = dev_addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 2;
|
||||
msg[0].buf = buff;
|
||||
|
||||
|
||||
msg[1].addr = dev_addr;
|
||||
msg[1].flags = I2C_M_NOSTART;
|
||||
msg[1].len = lenght;
|
||||
msg[1].buf = buf;
|
||||
|
||||
|
||||
msgst.msgs = msg;
|
||||
msgst.nmsgs = 2;
|
||||
|
||||
|
||||
if (ioctl(file,I2C_RDWR,&msgst) < 0){
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: Transaction failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int block_read(int file,int dev_addr,int eeprom_addr,unsigned char *buf){
|
||||
|
||||
int ln;
|
||||
char buff[2]; //={0x0,0x0};
|
||||
|
||||
struct i2c_msg msg[2];
|
||||
|
||||
struct i2c_ioctl_rdwr_data {
|
||||
|
||||
struct i2c_msg *msgs; /* ptr to array of simple messages */
|
||||
int nmsgs; /* number of messages to exchange */
|
||||
} msgst;
|
||||
|
||||
|
||||
|
||||
made_address(eeprom_addr,buff);
|
||||
ln=0;
|
||||
//bar();
|
||||
|
||||
msg[0].addr = dev_addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 2;
|
||||
msg[0].buf = buff;
|
||||
|
||||
|
||||
msg[1].addr = dev_addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
msg[1].len = MAX_BLK_SIZE;
|
||||
msg[1].buf = buf;
|
||||
|
||||
|
||||
|
||||
|
||||
msgst.msgs = msg;
|
||||
msgst.nmsgs = 2;
|
||||
|
||||
|
||||
|
||||
|
||||
if ((ln = ioctl(file, I2C_RDWR, &msgst)) < 0) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: Read error:%d\n",ln);
|
||||
return ln;
|
||||
}
|
||||
|
||||
return ln;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void made_address(int addr,unsigned char *buf){
|
||||
|
||||
int k;
|
||||
|
||||
//addr = addr & 0xFFFF; /*odstranim nepoterbne bity*/
|
||||
|
||||
k=addr;
|
||||
buf[1]=(unsigned char) (k & 0xFF); //vyrobim druhy byte adresy
|
||||
k=addr & 0xFF00 ;
|
||||
buf[0]= ((unsigned char) (k >> 8)) & 0x7F;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int init(char *device,int addr) {
|
||||
|
||||
int file;
|
||||
unsigned long funcs;
|
||||
|
||||
if ((file = open(device,O_RDWR)) < 0) {
|
||||
|
||||
fprintf(stderr,"Error: Could not open file %s\n",
|
||||
device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* check adapter functionality */
|
||||
if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
|
||||
fprintf(stderr,
|
||||
"Error: Could not get the adapter functionality matrix: %s\n",
|
||||
strerror(errno));
|
||||
close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The I2C address */
|
||||
if (ioctl(file,I2C_SLAVE,addr) < 0) {
|
||||
/* ERROR HANDLING; you can check errno to see what went wrong */
|
||||
fprintf(stderr,
|
||||
"Error: Cannot communicate with slave: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
int content_write(int file, int addr){
|
||||
|
||||
unsigned char buf[MAX_BLK_SIZE];
|
||||
unsigned char pom;
|
||||
int i, j, k, delka, addr_cnt;
|
||||
|
||||
delka=0;
|
||||
addr_cnt=HEAD_SIZE;
|
||||
k=0;
|
||||
|
||||
for(j=0;j<MAX_BLK_SIZE;j++)
|
||||
buf[j]=0;
|
||||
|
||||
|
||||
|
||||
i=0;
|
||||
|
||||
for(;;) {
|
||||
|
||||
delka=fread(&pom,1,1,stdin);
|
||||
|
||||
if( delka > 0 ){
|
||||
buf[i]=pom;
|
||||
}
|
||||
|
||||
if(i==(MAX_BLK_SIZE-1) || (delka < 1)) {
|
||||
|
||||
|
||||
|
||||
if(block_write(file,addr,addr_cnt,buf,delka<1?i:(i+1)) !=0) {
|
||||
|
||||
fprintf(stderr,"Block write failed\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
//printf("i:%d\n",i);
|
||||
addr_cnt=addr_cnt + i + (delka==1?1:0); //+i
|
||||
|
||||
for(j=0;j<MAX_BLK_SIZE;j++)
|
||||
buf[j]=0;
|
||||
|
||||
i=0;
|
||||
if(delka<1) {
|
||||
|
||||
//pisu EOF
|
||||
|
||||
|
||||
if(inode_write(file,addr,(addr_cnt-HEAD_SIZE)) !=0) {
|
||||
|
||||
fprintf(stderr,"Inode write failed\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
} else i++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int content_read(int file, int addr){
|
||||
|
||||
unsigned char buf[MAX_BLK_SIZE];
|
||||
int i, j, k, delka;
|
||||
|
||||
delka=0;
|
||||
k=0;
|
||||
|
||||
|
||||
inode_read(file,addr,p_ind );
|
||||
|
||||
|
||||
for(i=HEAD_SIZE;i<= (HEAD_SIZE + p_ind->data_len);i=i+MAX_BLK_SIZE ) {
|
||||
|
||||
|
||||
if(block_read(file,addr,i,buf) !=0) {
|
||||
|
||||
fprintf(stderr,"Block read failed\n");
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
if( (HEAD_SIZE + p_ind->data_len - i) < MAX_BLK_SIZE ) {
|
||||
k= HEAD_SIZE + p_ind->data_len - i;
|
||||
}else {
|
||||
k=MAX_BLK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
for(j=0;j<k ;j++){
|
||||
|
||||
putc(buf[j],stdout);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void erase(int file, int addr,int eeprom_size){
|
||||
|
||||
unsigned char buf[MAX_BLK_SIZE];
|
||||
int i, j, k, delka;
|
||||
|
||||
delka=0;
|
||||
k=0;
|
||||
|
||||
for(j=0;j<MAX_BLK_SIZE;j++)
|
||||
buf[j]=0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for(i=0;i<eeprom_size;i=i+MAX_BLK_SIZE) {
|
||||
|
||||
|
||||
if(block_write(file,addr,i,buf,MAX_BLK_SIZE) !=0) {
|
||||
|
||||
fprintf(stderr,"Block write failed\n");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bar(void){
|
||||
|
||||
|
||||
if( stav > 70 ) stav=0;
|
||||
|
||||
|
||||
switch(stav) {
|
||||
|
||||
|
||||
case 10: fwrite("\\",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
case 20: fwrite("|",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
case 30: fwrite("/",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
case 40: fwrite("-",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
case 50: fwrite("\\",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
case 60: fwrite("|",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
case 70: fwrite("/",1,1,stderr);
|
||||
fflush(stderr);
|
||||
rewind(stderr);
|
||||
break;
|
||||
}
|
||||
stav++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int inode_write(int file,int dev_addr,int lenght){
|
||||
|
||||
unsigned char buff[2];
|
||||
struct i2c_msg msg[2];
|
||||
|
||||
struct i2c_ioctl_rdwr_data {
|
||||
|
||||
struct i2c_msg *msgs; /* ptr to array of simple messages */
|
||||
int nmsgs; /* number of messages to exchange */
|
||||
} msgst;
|
||||
|
||||
|
||||
m_ind.timestamp=time(NULL);
|
||||
m_ind.data_len=lenght;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//bar();
|
||||
|
||||
made_address(START_ADDR,buff);
|
||||
|
||||
|
||||
msg[0].addr = dev_addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 2;
|
||||
msg[0].buf = buff;
|
||||
|
||||
|
||||
msg[1].addr = dev_addr;
|
||||
msg[1].flags = I2C_M_NOSTART;
|
||||
msg[1].len = sizeof(struct mini_inode);
|
||||
msg[1].buf = (char *) &m_ind;
|
||||
|
||||
|
||||
|
||||
msgst.msgs = msg;
|
||||
msgst.nmsgs = 2;
|
||||
|
||||
|
||||
if (ioctl(file,I2C_RDWR,&msgst) < 0){
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: Transaction failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int inode_read(int file,int dev_addr,void *p_inode ){
|
||||
|
||||
|
||||
#define POK 32
|
||||
int ln;
|
||||
char buff[2]; //={0x0,0x0};
|
||||
|
||||
struct i2c_msg msg[2];
|
||||
|
||||
struct i2c_ioctl_rdwr_data {
|
||||
|
||||
struct i2c_msg *msgs; /* ptr to array of simple messages */
|
||||
int nmsgs; /* number of messages to exchange */
|
||||
} msgst;
|
||||
|
||||
made_address(START_ADDR,buff);
|
||||
|
||||
ln=0;
|
||||
//bar();
|
||||
|
||||
msg[0].addr = dev_addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 2;
|
||||
msg[0].buf = buff;
|
||||
|
||||
|
||||
msg[1].addr = dev_addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
msg[1].len = sizeof(struct mini_inode);
|
||||
msg[1].buf = p_inode;
|
||||
|
||||
|
||||
|
||||
|
||||
msgst.msgs = msg;
|
||||
msgst.nmsgs = 2;
|
||||
|
||||
|
||||
if ((ln = ioctl(file, I2C_RDWR, &msgst)) < 0) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: Read error:%d\n",ln);
|
||||
return ln;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ln;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void pheader(int file,int dev_addr){
|
||||
|
||||
struct tm *p_tm;
|
||||
char time_buf[15],*p_buf;
|
||||
|
||||
p_buf=time_buf;
|
||||
inode_read(file,dev_addr,p_ind );
|
||||
p_tm=localtime(&p_ind->timestamp);
|
||||
strftime(p_buf,sizeof(time_buf),"%Y%m%d%H%M%S",p_tm);
|
||||
printf("LEN=%d,TIME=%s\n",p_ind->data_len,p_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef WARNINC
|
||||
void warn(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,"\n\n!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
fprintf(stderr,"This program is intended for use on eeproms\nusing external busses such as i2c-pport.\n");
|
||||
fprintf(stderr,"Do not use this on your SDRAM DIMM EEPROMS\nunless you REALLY REALLY know what you are\ndoing!!! Doing so will render your SDRAM\nUSELESS and leave your system UNBOOTABLE!!!\n");
|
||||
fprintf(stderr,"To disable this warning use -force\n");
|
||||
fprintf(stderr,"\n\nPress ENTER to continue or hit Control-C NOW !!!!\n\n\n");
|
||||
|
||||
getchar();
|
||||
}
|
||||
#endif
|
||||
29
Script/i2c-tools-3.1.0/include/Module.mk
Normal file
29
Script/i2c-tools-3.1.0/include/Module.mk
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Linux I2C header files
|
||||
#
|
||||
# Copyright (C) 2007 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.
|
||||
|
||||
INCLUDE_DIR := include
|
||||
|
||||
INCLUDE_TARGETS := linux/i2c-dev.h
|
||||
|
||||
#
|
||||
# Commands
|
||||
#
|
||||
|
||||
install-include: $(addprefix $(INCLUDE_DIR)/,$(INCLUDE_TARGETS))
|
||||
$(INSTALL_DIR) $(DESTDIR)$(incdir)/linux
|
||||
for file in $(INCLUDE_TARGETS) ; do \
|
||||
$(INSTALL_DATA) $(INCLUDE_DIR)/$$file $(DESTDIR)$(incdir)/$$file ; done
|
||||
|
||||
uninstall-include:
|
||||
for file in $(INCLUDE_TARGETS) ; do \
|
||||
$(RM) $(DESTDIR)$(incdir)/$$file ; done
|
||||
|
||||
install: install-include
|
||||
|
||||
uninstall: uninstall-include
|
||||
335
Script/i2c-tools-3.1.0/include/linux/i2c-dev.h
Normal file
335
Script/i2c-tools-3.1.0/include/linux/i2c-dev.h
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
i2c-dev.h - i2c-bus driver, char device interface
|
||||
|
||||
Copyright (C) 1995-97 Simon G. Vogl
|
||||
Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* $Id: i2c-dev.h 5894 2010-12-12 13:22:29Z khali $ */
|
||||
|
||||
#ifndef LIB_I2CDEV_H
|
||||
#define LIB_I2CDEV_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
/* -- i2c.h -- */
|
||||
|
||||
|
||||
/*
|
||||
* I2C Message - used for pure i2c transaction, also from /dev interface
|
||||
*/
|
||||
struct i2c_msg {
|
||||
__u16 addr; /* slave address */
|
||||
unsigned short flags;
|
||||
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
|
||||
#define I2C_M_RD 0x01
|
||||
#define I2C_M_NOSTART 0x4000
|
||||
#define I2C_M_REV_DIR_ADDR 0x2000
|
||||
#define I2C_M_IGNORE_NAK 0x1000
|
||||
#define I2C_M_NO_RD_ACK 0x0800
|
||||
short len; /* msg length */
|
||||
char *buf; /* pointer to msg data */
|
||||
};
|
||||
|
||||
/* To determine what functionality is present */
|
||||
|
||||
#define I2C_FUNC_I2C 0x00000001
|
||||
#define I2C_FUNC_10BIT_ADDR 0x00000002
|
||||
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
|
||||
#define I2C_FUNC_SMBUS_PEC 0x00000008
|
||||
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
|
||||
#define I2C_FUNC_SMBUS_QUICK 0x00010000
|
||||
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
|
||||
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
|
||||
#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
|
||||
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
|
||||
#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
|
||||
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
|
||||
#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
|
||||
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
|
||||
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
|
||||
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
|
||||
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
|
||||
|
||||
#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE)
|
||||
#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
|
||||
#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
|
||||
I2C_FUNC_SMBUS_WRITE_WORD_DATA)
|
||||
#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
|
||||
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
|
||||
#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
|
||||
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
|
||||
|
||||
/* Old name, for compatibility */
|
||||
#define I2C_FUNC_SMBUS_HWPEC_CALC I2C_FUNC_SMBUS_PEC
|
||||
|
||||
/*
|
||||
* Data for SMBus Messages
|
||||
*/
|
||||
#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
|
||||
#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
|
||||
union i2c_smbus_data {
|
||||
__u8 byte;
|
||||
__u16 word;
|
||||
__u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
|
||||
/* and one more for PEC */
|
||||
};
|
||||
|
||||
/* smbus_access read or write markers */
|
||||
#define I2C_SMBUS_READ 1
|
||||
#define I2C_SMBUS_WRITE 0
|
||||
|
||||
/* SMBus transaction types (size parameter in the above functions)
|
||||
Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
|
||||
#define I2C_SMBUS_QUICK 0
|
||||
#define I2C_SMBUS_BYTE 1
|
||||
#define I2C_SMBUS_BYTE_DATA 2
|
||||
#define I2C_SMBUS_WORD_DATA 3
|
||||
#define I2C_SMBUS_PROC_CALL 4
|
||||
#define I2C_SMBUS_BLOCK_DATA 5
|
||||
#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
|
||||
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
|
||||
#define I2C_SMBUS_I2C_BLOCK_DATA 8
|
||||
|
||||
|
||||
/* ----- commands for the ioctl like i2c_command call:
|
||||
* note that additional calls are defined in the algorithm and hw
|
||||
* dependent layers - these can be listed here, or see the
|
||||
* corresponding header files.
|
||||
*/
|
||||
/* -> bit-adapter specific ioctls */
|
||||
#define I2C_RETRIES 0x0701 /* number of times a device address */
|
||||
/* should be polled when not */
|
||||
/* acknowledging */
|
||||
#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
|
||||
|
||||
|
||||
/* this is for i2c-dev.c */
|
||||
#define I2C_SLAVE 0x0703 /* Change slave address */
|
||||
/* Attn.: Slave address is 7 or 10 bits */
|
||||
#define I2C_SLAVE_FORCE 0x0706 /* Change slave address */
|
||||
/* Attn.: Slave address is 7 or 10 bits */
|
||||
/* This changes the address, even if it */
|
||||
/* is already taken! */
|
||||
#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
|
||||
|
||||
#define I2C_FUNCS 0x0705 /* Get the adapter functionality */
|
||||
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
|
||||
#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
|
||||
|
||||
#define I2C_SMBUS 0x0720 /* SMBus-level access */
|
||||
|
||||
/* -- i2c.h -- */
|
||||
|
||||
|
||||
/* Note: 10-bit addresses are NOT supported! */
|
||||
|
||||
/* This is the structure as used in the I2C_SMBUS ioctl call */
|
||||
struct i2c_smbus_ioctl_data {
|
||||
char read_write;
|
||||
__u8 command;
|
||||
int size;
|
||||
union i2c_smbus_data *data;
|
||||
};
|
||||
|
||||
/* This is the structure as used in the I2C_RDWR ioctl call */
|
||||
struct i2c_rdwr_ioctl_data {
|
||||
struct i2c_msg *msgs; /* pointers to i2c_msgs */
|
||||
int nmsgs; /* number of i2c_msgs */
|
||||
};
|
||||
|
||||
|
||||
static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
|
||||
int size, union i2c_smbus_data *data)
|
||||
{
|
||||
struct i2c_smbus_ioctl_data args;
|
||||
|
||||
args.read_write = read_write;
|
||||
args.command = command;
|
||||
args.size = size;
|
||||
args.data = data;
|
||||
return ioctl(file,I2C_SMBUS,&args);
|
||||
}
|
||||
|
||||
|
||||
static inline __s32 i2c_smbus_write_quick(int file, __u8 value)
|
||||
{
|
||||
return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_read_byte(int file)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
|
||||
return -1;
|
||||
else
|
||||
return 0x0FF & data.byte;
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_write_byte(int file, __u8 value)
|
||||
{
|
||||
return i2c_smbus_access(file,I2C_SMBUS_WRITE,value,
|
||||
I2C_SMBUS_BYTE,NULL);
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
|
||||
I2C_SMBUS_BYTE_DATA,&data))
|
||||
return -1;
|
||||
else
|
||||
return 0x0FF & data.byte;
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
|
||||
__u8 value)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
data.byte = value;
|
||||
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
|
||||
I2C_SMBUS_BYTE_DATA, &data);
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
|
||||
I2C_SMBUS_WORD_DATA,&data))
|
||||
return -1;
|
||||
else
|
||||
return 0x0FFFF & data.word;
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_write_word_data(int file, __u8 command,
|
||||
__u16 value)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
data.word = value;
|
||||
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
|
||||
I2C_SMBUS_WORD_DATA, &data);
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
data.word = value;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
|
||||
I2C_SMBUS_PROC_CALL,&data))
|
||||
return -1;
|
||||
else
|
||||
return 0x0FFFF & data.word;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the number of read bytes */
|
||||
static inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
|
||||
__u8 *values)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
int i;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
|
||||
I2C_SMBUS_BLOCK_DATA,&data))
|
||||
return -1;
|
||||
else {
|
||||
for (i = 1; i <= data.block[0]; i++)
|
||||
values[i-1] = data.block[i];
|
||||
return data.block[0];
|
||||
}
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
|
||||
__u8 length, const __u8 *values)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
int i;
|
||||
if (length > 32)
|
||||
length = 32;
|
||||
for (i = 1; i <= length; i++)
|
||||
data.block[i] = values[i-1];
|
||||
data.block[0] = length;
|
||||
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
|
||||
I2C_SMBUS_BLOCK_DATA, &data);
|
||||
}
|
||||
|
||||
/* Returns the number of read bytes */
|
||||
/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
|
||||
ask for less than 32 bytes, your code will only work with kernels
|
||||
2.6.23 and later. */
|
||||
static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command,
|
||||
__u8 length, __u8 *values)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
int i;
|
||||
|
||||
if (length > 32)
|
||||
length = 32;
|
||||
data.block[0] = length;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
|
||||
length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
|
||||
I2C_SMBUS_I2C_BLOCK_DATA,&data))
|
||||
return -1;
|
||||
else {
|
||||
for (i = 1; i <= data.block[0]; i++)
|
||||
values[i-1] = data.block[i];
|
||||
return data.block[0];
|
||||
}
|
||||
}
|
||||
|
||||
static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
|
||||
__u8 length,
|
||||
const __u8 *values)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
int i;
|
||||
if (length > 32)
|
||||
length = 32;
|
||||
for (i = 1; i <= length; i++)
|
||||
data.block[i] = values[i-1];
|
||||
data.block[0] = length;
|
||||
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
|
||||
I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
|
||||
}
|
||||
|
||||
/* Returns the number of read bytes */
|
||||
static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
|
||||
__u8 length, __u8 *values)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
int i;
|
||||
if (length > 32)
|
||||
length = 32;
|
||||
for (i = 1; i <= length; i++)
|
||||
data.block[i] = values[i-1];
|
||||
data.block[0] = length;
|
||||
if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
|
||||
I2C_SMBUS_BLOCK_PROC_CALL,&data))
|
||||
return -1;
|
||||
else {
|
||||
for (i = 1; i <= data.block[0]; i++)
|
||||
values[i-1] = data.block[i];
|
||||
return data.block[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* LIB_I2CDEV_H */
|
||||
31
Script/i2c-tools-3.1.0/py-smbus/Module.mk
Normal file
31
Script/i2c-tools-3.1.0/py-smbus/Module.mk
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Python bindings for Linux SMBus access through i2c-dev
|
||||
#
|
||||
# Copyright (C) 2009 Mike Frysinger <vapier@gentoo.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.
|
||||
|
||||
PY_SMBUS_DIR := py-smbus
|
||||
|
||||
PYTHON ?= python
|
||||
DISTUTILS := \
|
||||
cd $(PY_SMBUS_DIR) && \
|
||||
CPPFLAGS="$(CPPFLAGS) -I../include" $(PYTHON) setup.py
|
||||
|
||||
all-python: $(INCLUDE_DIR)/linux/i2c-dev.h
|
||||
$(DISTUTILS) build
|
||||
|
||||
clean-python:
|
||||
$(DISTUTILS) clean
|
||||
rm -rf py-smbus/build
|
||||
|
||||
install-python:
|
||||
$(DISTUTILS) install
|
||||
|
||||
all: all-python
|
||||
|
||||
clean: clean-python
|
||||
|
||||
install: install-python
|
||||
26
Script/i2c-tools-3.1.0/py-smbus/README
Normal file
26
Script/i2c-tools-3.1.0/py-smbus/README
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
README: py-smbus
|
||||
|
||||
To build:
|
||||
$ python setup.py build
|
||||
On most GNU/Linux distributions, you'll need to install the python-devel
|
||||
package for the build to succeed.
|
||||
|
||||
To install (will also build if necessary):
|
||||
$ python setup.py install
|
||||
|
||||
For general build/install help:
|
||||
$ python setup.py --help-commands
|
||||
|
||||
Frequently Answered Question:
|
||||
|
||||
Q: It's throwing exceptions, nothing works, what's wrong?
|
||||
|
||||
A1: You need write permissions to the i2c-dev devices. Try running as root.
|
||||
|
||||
A2: Addresses in Linux/I2C are the most-sig 7 bits, right-justified. E.g.
|
||||
if your device uses address 0xc0 to write and 0xc1 to read, then use
|
||||
address 0x60 with this module.
|
||||
|
||||
A3: Some other kernel driver has claimed that I2C address. Unload it first.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
14
Script/i2c-tools-3.1.0/py-smbus/setup.py
Normal file
14
Script/i2c-tools-3.1.0/py-smbus/setup.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
setup( name="smbus",
|
||||
version="1.1",
|
||||
description="Python bindings for Linux SMBus access through i2c-dev",
|
||||
author="Mark M. Hoffman",
|
||||
author_email="mhoffman@lightlink.com",
|
||||
maintainer="Mark M. Hoffman",
|
||||
maintainer_email="linux-i2c@vger.kernel.org",
|
||||
license="GPLv2",
|
||||
url="http://lm-sensors.org/",
|
||||
ext_modules=[Extension("smbus", ["smbusmodule.c"])])
|
||||
730
Script/i2c-tools-3.1.0/py-smbus/smbusmodule.c
Normal file
730
Script/i2c-tools-3.1.0/py-smbus/smbusmodule.c
Normal file
|
|
@ -0,0 +1,730 @@
|
|||
/*
|
||||
* smbusmodule.c - Python bindings for Linux SMBus access through i2c-dev
|
||||
* Copyright (C) 2005-2007 Mark M. Hoffman <mhoffman@xxxxxxxxxxxxx>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "structmember.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
|
||||
/*
|
||||
** These are required to build this module against Linux older than 2.6.23.
|
||||
*/
|
||||
#ifndef I2C_SMBUS_I2C_BLOCK_BROKEN
|
||||
#undef I2C_SMBUS_I2C_BLOCK_DATA
|
||||
#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
|
||||
#define I2C_SMBUS_I2C_BLOCK_DATA 8
|
||||
#endif
|
||||
|
||||
/*yDoc_STRVAR(SMBus_module_doc,
|
||||
"This module defines an object type that allows SMBus transactions\n"
|
||||
"on hosts running the Linux kernel. The host kernel must have I2C\n"
|
||||
"support, I2C device interface support, and a bus adapter driver.\n"
|
||||
"All of these can be either built-in to the kernel, or loaded from\n"
|
||||
"modules.\n"
|
||||
"\n"
|
||||
"Because the I2C device interface is opened R/W, users of this\n"
|
||||
"module usually must have root permissions.\n");
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
int fd; /* open file descriptor: /dev/i2c-?, or -1 */
|
||||
int addr; /* current client SMBus address */
|
||||
int pec; /* !0 => Packet Error Codes enabled */
|
||||
} SMBus;
|
||||
|
||||
static PyObject *
|
||||
SMBus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
SMBus *self;
|
||||
|
||||
if ((self = (SMBus *)type->tp_alloc(type, 0)) == NULL)
|
||||
return NULL;
|
||||
|
||||
self->fd = -1;
|
||||
self->addr = -1;
|
||||
self->pec = 0;
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_close_doc,
|
||||
"close()\n\n"
|
||||
"Disconnects the object from the bus.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_close(SMBus *self)
|
||||
{
|
||||
if ((self->fd != -1) && (close(self->fd) == -1)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->fd = -1;
|
||||
self->addr = -1;
|
||||
self->pec = 0;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static void
|
||||
SMBus_dealloc(SMBus *self)
|
||||
{
|
||||
PyObject *ref = SMBus_close(self);
|
||||
Py_XDECREF(ref);
|
||||
|
||||
/*old python 2.7 declaration */
|
||||
/*self->ob_type->tp_free((PyObject *)self);*/
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
#define MAXPATH 16
|
||||
|
||||
PyDoc_STRVAR(SMBus_open_doc,
|
||||
"open(bus)\n\n"
|
||||
"Connects the object to the specified SMBus.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_open(SMBus *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
int bus;
|
||||
char path[MAXPATH];
|
||||
|
||||
static char *kwlist[] = {"bus", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:open", kwlist, &bus))
|
||||
return NULL;
|
||||
|
||||
if (snprintf(path, MAXPATH, "/dev/i2c-%d", bus) >= MAXPATH) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"Bus number is invalid.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((self->fd = open(path, O_RDWR, 0)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static int
|
||||
SMBus_init(SMBus *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
int bus = -1;
|
||||
|
||||
static char *kwlist[] = {"bus", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:__init__",
|
||||
kwlist, &bus))
|
||||
return -1;
|
||||
|
||||
if (bus >= 0) {
|
||||
SMBus_open(self, args, kwds);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* private helper function, 0 => success, !0 => error
|
||||
*/
|
||||
static int
|
||||
SMBus_set_addr(SMBus *self, int addr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (self->addr != addr) {
|
||||
ret = ioctl(self->fd, I2C_SLAVE, addr);
|
||||
self->addr = addr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SMBus_SET_ADDR(self, addr) do { \
|
||||
if (SMBus_set_addr(self, addr)) { \
|
||||
PyErr_SetFromErrno(PyExc_IOError); \
|
||||
return NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
PyDoc_STRVAR(SMBus_write_quick_doc,
|
||||
"write_quick(addr)\n\n"
|
||||
"Perform SMBus Quick transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_write_quick(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:write_quick", &addr))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_write_quick(self->fd, I2C_SMBUS_WRITE))) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_read_byte_doc,
|
||||
"read_byte(addr) -> result\n\n"
|
||||
"Perform SMBus Read Byte transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_read_byte(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:read_byte", &addr))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_read_byte(self->fd)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("l", (long)result);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_write_byte_doc,
|
||||
"write_byte(addr, val)\n\n"
|
||||
"Perform SMBus Write Byte transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_write_byte(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, val;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii:write_byte", &addr, &val))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_write_byte(self->fd, (__u8)val)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_read_byte_data_doc,
|
||||
"read_byte_data(addr, cmd) -> result\n\n"
|
||||
"Perform SMBus Read Byte Data transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_read_byte_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii:read_byte_data", &addr, &cmd))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_read_byte_data(self->fd, (__u8)cmd)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("l", (long)result);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_write_byte_data_doc,
|
||||
"write_byte_data(addr, cmd, val)\n\n"
|
||||
"Perform SMBus Write Byte Data transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_write_byte_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd, val;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iii:write_byte_data", &addr, &cmd, &val))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_write_byte_data(self->fd,
|
||||
(__u8)cmd, (__u8)val)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_read_word_data_doc,
|
||||
"read_word_data(addr, cmd) -> result\n\n"
|
||||
"Perform SMBus Read Word Data transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_read_word_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii:read_word_data", &addr, &cmd))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_read_word_data(self->fd, (__u8)cmd)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("l", (long)result);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_write_word_data_doc,
|
||||
"write_word_data(addr, cmd, val)\n\n"
|
||||
"Perform SMBus Write Word Data transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_write_word_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd, val;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iii:write_word_data", &addr, &cmd, &val))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_write_word_data(self->fd,
|
||||
(__u8)cmd, (__u16)val)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_process_call_doc,
|
||||
"process_call(addr, cmd, val)\n\n"
|
||||
"Perform SMBus Process Call transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_process_call(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd, val;
|
||||
__s32 result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iii:process_call", &addr, &cmd, &val))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
if ((result = i2c_smbus_process_call(self->fd,
|
||||
(__u8)cmd, (__u16)val)) == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/*
|
||||
* private helper function; returns a new list of integers
|
||||
*/
|
||||
static PyObject *
|
||||
SMBus_buf_to_list(__u8 const *buf, int len)
|
||||
{
|
||||
PyObject *list = PyList_New(len);
|
||||
int ii;
|
||||
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
for (ii = 0; ii < len; ii++) {
|
||||
PyObject *val = Py_BuildValue("l", (long)buf[ii]);
|
||||
PyList_SET_ITEM(list, ii, val);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_read_block_data_doc,
|
||||
"read_block_data(addr, cmd) -> results\n\n"
|
||||
"Perform SMBus Read Block Data transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_read_block_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd;
|
||||
union i2c_smbus_data data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii:read_block_data", &addr, &cmd))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
/* save a bit of code by calling the access function directly */
|
||||
if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd,
|
||||
I2C_SMBUS_BLOCK_DATA, &data)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first byte of the block contains (remaining) data length */
|
||||
return SMBus_buf_to_list(&data.block[1], data.block[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* private helper function: convert an integer list to union i2c_smbus_data
|
||||
*/
|
||||
static int
|
||||
SMBus_list_to_data(PyObject *list, union i2c_smbus_data *data)
|
||||
{
|
||||
static char *msg = "Third argument must be a list of at least one, "
|
||||
"but not more than 32 integers";
|
||||
int ii, len;
|
||||
|
||||
if (!PyList_Check(list)) {
|
||||
PyErr_SetString(PyExc_TypeError, msg);
|
||||
return 0; /* fail */
|
||||
}
|
||||
|
||||
if ((len = PyList_GET_SIZE(list)) > 32) {
|
||||
PyErr_SetString(PyExc_OverflowError, msg);
|
||||
return 0; /* fail */
|
||||
}
|
||||
|
||||
/* first byte is the length */
|
||||
data->block[0] = (__u8)len;
|
||||
|
||||
for (ii = 0; ii < len; ii++) {
|
||||
PyObject *val = PyList_GET_ITEM(list, ii);
|
||||
if (!PyLong_Check(val)) {
|
||||
PyErr_SetString(PyExc_TypeError, msg);
|
||||
return 0; /* fail */
|
||||
}
|
||||
data->block[ii+1] = (__u8)PyLong_AS_LONG(val);
|
||||
}
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_write_block_data_doc,
|
||||
"write_block_data(addr, cmd, [vals])\n\n"
|
||||
"Perform SMBus Write Block Data transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_write_block_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd;
|
||||
union i2c_smbus_data data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiO&:write_block_data", &addr, &cmd,
|
||||
SMBus_list_to_data, &data))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
/* save a bit of code by calling the access function directly */
|
||||
if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
|
||||
I2C_SMBUS_BLOCK_DATA, &data)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_block_process_call_doc,
|
||||
"block_process_call(addr, cmd, [vals]) -> results\n\n"
|
||||
"Perform SMBus Block Process Call transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_block_process_call(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd;
|
||||
union i2c_smbus_data data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiO&:block_process_call", &addr, &cmd,
|
||||
SMBus_list_to_data, &data))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
/* save a bit of code by calling the access function directly */
|
||||
if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
|
||||
I2C_SMBUS_BLOCK_PROC_CALL, &data)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first byte of the block contains (remaining) data length */
|
||||
return SMBus_buf_to_list(&data.block[1], data.block[0]);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_read_i2c_block_data_doc,
|
||||
"read_i2c_block_data(addr, cmd, len=32) -> results\n\n"
|
||||
"Perform I2C Block Read transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_read_i2c_block_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd, len=32;
|
||||
union i2c_smbus_data data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii|i:read_i2c_block_data", &addr, &cmd,
|
||||
&len))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
data.block[0] = len;
|
||||
/* save a bit of code by calling the access function directly */
|
||||
if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd,
|
||||
len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN:
|
||||
I2C_SMBUS_I2C_BLOCK_DATA, &data)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first byte of the block contains (remaining) data length */
|
||||
return SMBus_buf_to_list(&data.block[1], data.block[0]);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_write_i2c_block_data_doc,
|
||||
"write_i2c_block_data(addr, cmd, [vals])\n\n"
|
||||
"Perform I2C Block Write transaction.\n");
|
||||
|
||||
static PyObject *
|
||||
SMBus_write_i2c_block_data(SMBus *self, PyObject *args)
|
||||
{
|
||||
int addr, cmd;
|
||||
union i2c_smbus_data data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiO&:write_i2c_block_data", &addr, &cmd,
|
||||
SMBus_list_to_data, &data))
|
||||
return NULL;
|
||||
|
||||
SMBus_SET_ADDR(self, addr);
|
||||
|
||||
/* save a bit of code by calling the access function directly */
|
||||
if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
|
||||
I2C_SMBUS_I2C_BLOCK_BROKEN, &data)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(SMBus_type_doc,
|
||||
"SMBus([bus]) -> SMBus\n\n"
|
||||
"Return a new SMBus object that is (optionally) connected to the\n"
|
||||
"specified I2C device interface.\n");
|
||||
|
||||
static PyMethodDef SMBus_methods[] = {
|
||||
{"open", (PyCFunction)SMBus_open, METH_VARARGS | METH_KEYWORDS,
|
||||
SMBus_open_doc},
|
||||
{"close", (PyCFunction)SMBus_close, METH_NOARGS,
|
||||
SMBus_close_doc},
|
||||
{"write_quick", (PyCFunction)SMBus_write_quick, METH_VARARGS,
|
||||
SMBus_write_quick_doc},
|
||||
{"read_byte", (PyCFunction)SMBus_read_byte, METH_VARARGS,
|
||||
SMBus_read_byte_doc},
|
||||
{"write_byte", (PyCFunction)SMBus_write_byte, METH_VARARGS,
|
||||
SMBus_write_byte_doc},
|
||||
{"read_byte_data", (PyCFunction)SMBus_read_byte_data, METH_VARARGS,
|
||||
SMBus_read_byte_data_doc},
|
||||
{"write_byte_data", (PyCFunction)SMBus_write_byte_data, METH_VARARGS,
|
||||
SMBus_write_byte_data_doc},
|
||||
{"read_word_data", (PyCFunction)SMBus_read_word_data, METH_VARARGS,
|
||||
SMBus_read_word_data_doc},
|
||||
{"write_word_data", (PyCFunction)SMBus_write_word_data, METH_VARARGS,
|
||||
SMBus_write_word_data_doc},
|
||||
{"process_call", (PyCFunction)SMBus_process_call, METH_VARARGS,
|
||||
SMBus_process_call_doc},
|
||||
{"read_block_data", (PyCFunction)SMBus_read_block_data, METH_VARARGS,
|
||||
SMBus_read_block_data_doc},
|
||||
{"write_block_data", (PyCFunction)SMBus_write_block_data, METH_VARARGS,
|
||||
SMBus_write_block_data_doc},
|
||||
{"block_process_call", (PyCFunction)SMBus_block_process_call,
|
||||
METH_VARARGS, SMBus_block_process_call_doc},
|
||||
{"read_i2c_block_data", (PyCFunction)SMBus_read_i2c_block_data,
|
||||
METH_VARARGS, SMBus_read_i2c_block_data_doc},
|
||||
{"write_i2c_block_data", (PyCFunction)SMBus_write_i2c_block_data,
|
||||
METH_VARARGS, SMBus_write_i2c_block_data_doc},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
SMBus_get_pec(SMBus *self, void *closure)
|
||||
{
|
||||
PyObject *result = self->pec ? Py_True : Py_False;
|
||||
Py_INCREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
SMBus_set_pec(SMBus *self, PyObject *val, void *closure)
|
||||
{
|
||||
int pec;
|
||||
|
||||
pec = PyObject_IsTrue(val);
|
||||
|
||||
if (val == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Cannot delete attribute");
|
||||
return -1;
|
||||
}
|
||||
else if (pec == -1) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The pec attribute must be a boolean.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (self->pec != pec) {
|
||||
if (ioctl(self->fd, I2C_PEC, pec)) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return -1;
|
||||
}
|
||||
self->pec = pec;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyGetSetDef SMBus_getset[] = {
|
||||
{"pec", (getter)SMBus_get_pec, (setter)SMBus_set_pec,
|
||||
"True if Packet Error Codes (PEC) are enabled"},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* old Python 2.7 declaration */
|
||||
static PyTypeObject SMBus_type = {
|
||||
/*tatic struct PyModuleDef SMBus_type = {*/
|
||||
/* old Python 2.7 declaration */
|
||||
/* PyObject_HEAD_INIT(NULL) */
|
||||
/*0, ob_size */
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"SMBus", /* tp_name */
|
||||
sizeof(SMBus), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)SMBus_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
SMBus_type_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
SMBus_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
SMBus_getset, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)SMBus_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
SMBus_new, /* tp_new */
|
||||
};
|
||||
|
||||
/*static PyMethodDef SMBus_module_methods[] = {
|
||||
{NULL}
|
||||
};*/
|
||||
|
||||
static struct PyModuleDef SMBusModule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"SMBus", /* m_name */
|
||||
"This module defines an object type that allows SMBus transactions\n"
|
||||
"on hosts running the Linux kernel. The host kernel must have I2C\n"
|
||||
"support, I2C device interface support, and a bus adapter driver.\n"
|
||||
"All of these can be either built-in to the kernel, or loaded from\n"
|
||||
"modules.\n"
|
||||
"\n"
|
||||
"Because the I2C device interface is opened R/W, users of this\n"
|
||||
"module usually must have root permissions.\n", /* m_doc */
|
||||
-1, /* m_size */
|
||||
NULL, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
|
||||
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
|
||||
#define PyMODINIT_FUNC void
|
||||
#endif
|
||||
PyMODINIT_FUNC
|
||||
PyInit_smbus(void)
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
if (PyType_Ready(&SMBus_type) < 0)
|
||||
return NULL;
|
||||
|
||||
/* old Python 2.7 declaration */
|
||||
/*m = Py_InitModule3("smbus", SMBus_module_methods, SMBus_module_doc);*/
|
||||
m = PyModule_Create(&SMBusModule);
|
||||
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(&SMBus_type);
|
||||
PyModule_AddObject(m, "SMBus", (PyObject *)&SMBus_type);
|
||||
|
||||
return m;
|
||||
}
|
||||
27
Script/i2c-tools-3.1.0/stub/Module.mk
Normal file
27
Script/i2c-tools-3.1.0/stub/Module.mk
Normal 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
|
||||
229
Script/i2c-tools-3.1.0/stub/i2c-stub-from-dump
Normal file
229
Script/i2c-tools-3.1.0/stub/i2c-stub-from-dump
Normal 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);
|
||||
52
Script/i2c-tools-3.1.0/stub/i2c-stub-from-dump.8
Normal file
52
Script/i2c-tools-3.1.0/stub/i2c-stub-from-dump.8
Normal 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
|
||||
87
Script/i2c-tools-3.1.0/tools/Module.mk
Normal file
87
Script/i2c-tools-3.1.0/tools/Module.mk
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# I2C tools for Linux
|
||||
#
|
||||
# Copyright (C) 2007 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.
|
||||
|
||||
TOOLS_DIR := tools
|
||||
|
||||
TOOLS_CFLAGS := -Wstrict-prototypes -Wshadow -Wpointer-arith -Wcast-qual \
|
||||
-Wcast-align -Wwrite-strings -Wnested-externs -Winline \
|
||||
-W -Wundef -Wmissing-prototypes -Iinclude
|
||||
|
||||
TOOLS_TARGETS := i2cdetect i2cdump i2cset i2cget
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
$(TOOLS_DIR)/i2cdetect: $(TOOLS_DIR)/i2cdetect.o $(TOOLS_DIR)/i2cbusses.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
$(TOOLS_DIR)/i2cdump: $(TOOLS_DIR)/i2cdump.o $(TOOLS_DIR)/i2cbusses.o $(TOOLS_DIR)/util.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
$(TOOLS_DIR)/i2cset: $(TOOLS_DIR)/i2cset.o $(TOOLS_DIR)/i2cbusses.o $(TOOLS_DIR)/util.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
$(TOOLS_DIR)/i2cget: $(TOOLS_DIR)/i2cget.o $(TOOLS_DIR)/i2cbusses.o $(TOOLS_DIR)/util.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
#
|
||||
# Objects
|
||||
#
|
||||
|
||||
$(TOOLS_DIR)/i2cdetect.o: $(TOOLS_DIR)/i2cdetect.c $(TOOLS_DIR)/i2cbusses.h $(INCLUDE_DIR)/linux/i2c-dev.h
|
||||
$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@
|
||||
|
||||
$(TOOLS_DIR)/i2cdump.o: $(TOOLS_DIR)/i2cdump.c $(TOOLS_DIR)/i2cbusses.h $(TOOLS_DIR)/util.h $(INCLUDE_DIR)/linux/i2c-dev.h
|
||||
$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@
|
||||
|
||||
$(TOOLS_DIR)/i2cset.o: $(TOOLS_DIR)/i2cset.c $(TOOLS_DIR)/i2cbusses.h $(TOOLS_DIR)/util.h $(INCLUDE_DIR)/linux/i2c-dev.h
|
||||
$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@
|
||||
|
||||
$(TOOLS_DIR)/i2cget.o: $(TOOLS_DIR)/i2cget.c $(TOOLS_DIR)/i2cbusses.h $(TOOLS_DIR)/util.h $(INCLUDE_DIR)/linux/i2c-dev.h
|
||||
$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@
|
||||
|
||||
$(TOOLS_DIR)/i2cbusses.o: $(TOOLS_DIR)/i2cbusses.c $(TOOLS_DIR)/i2cbusses.h $(INCLUDE_DIR)/linux/i2c-dev.h
|
||||
$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@
|
||||
|
||||
$(TOOLS_DIR)/util.o: $(TOOLS_DIR)/util.c $(TOOLS_DIR)/util.h
|
||||
$(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@
|
||||
|
||||
#
|
||||
# Commands
|
||||
#
|
||||
|
||||
all-tools: $(addprefix $(TOOLS_DIR)/,$(TOOLS_TARGETS))
|
||||
|
||||
strip-tools: $(addprefix $(TOOLS_DIR)/,$(TOOLS_TARGETS))
|
||||
strip $(addprefix $(TOOLS_DIR)/,$(TOOLS_TARGETS))
|
||||
|
||||
clean-tools:
|
||||
$(RM) $(addprefix $(TOOLS_DIR)/,*.o $(TOOLS_TARGETS))
|
||||
|
||||
install-tools: $(addprefix $(TOOLS_DIR)/,$(TOOLS_TARGETS))
|
||||
$(INSTALL_DIR) $(DESTDIR)$(sbindir) $(DESTDIR)$(man8dir)
|
||||
for program in $(TOOLS_TARGETS) ; do \
|
||||
$(INSTALL_PROGRAM) $(TOOLS_DIR)/$$program $(DESTDIR)$(sbindir) ; \
|
||||
$(INSTALL_DATA) $(TOOLS_DIR)/$$program.8 $(DESTDIR)$(man8dir) ; done
|
||||
|
||||
uninstall-tools:
|
||||
for program in $(TOOLS_TARGETS) ; do \
|
||||
$(RM) $(DESTDIR)$(sbindir)/$$program ; \
|
||||
$(RM) $(DESTDIR)$(man8dir)/$$program.8 ; done
|
||||
|
||||
all: all-tools
|
||||
|
||||
strip: strip-tools
|
||||
|
||||
clean: clean-tools
|
||||
|
||||
install: install-tools
|
||||
|
||||
uninstall: uninstall-tools
|
||||
415
Script/i2c-tools-3.1.0/tools/i2cbusses.c
Normal file
415
Script/i2c-tools-3.1.0/tools/i2cbusses.c
Normal file
|
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
|
||||
Part of user-space programs to access for I2C
|
||||
devices.
|
||||
Copyright (c) 1999-2003 Frodo Looijaard <frodol@dds.nl> and
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2008-2010 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.
|
||||
*/
|
||||
|
||||
/* For strdup and snprintf */
|
||||
#define _BSD_SOURCE 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h> /* for NAME_MAX */
|
||||
#include <string.h>
|
||||
#include <strings.h> /* for strcasecmp() */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include "i2cbusses.h"
|
||||
#include <linux/i2c-dev.h>
|
||||
|
||||
enum adt { adt_dummy, adt_isa, adt_i2c, adt_smbus, adt_unknown };
|
||||
|
||||
struct adap_type {
|
||||
const char *funcs;
|
||||
const char* algo;
|
||||
};
|
||||
|
||||
static struct adap_type adap_types[5] = {
|
||||
{ .funcs = "dummy",
|
||||
.algo = "Dummy bus", },
|
||||
{ .funcs = "isa",
|
||||
.algo = "ISA bus", },
|
||||
{ .funcs = "i2c",
|
||||
.algo = "I2C adapter", },
|
||||
{ .funcs = "smbus",
|
||||
.algo = "SMBus adapter", },
|
||||
{ .funcs = "unknown",
|
||||
.algo = "N/A", },
|
||||
};
|
||||
|
||||
static enum adt i2c_get_funcs(int i2cbus)
|
||||
{
|
||||
unsigned long funcs;
|
||||
int file;
|
||||
char filename[20];
|
||||
enum adt ret;
|
||||
|
||||
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 1);
|
||||
if (file < 0)
|
||||
return adt_unknown;
|
||||
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0)
|
||||
ret = adt_unknown;
|
||||
else if (funcs & I2C_FUNC_I2C)
|
||||
ret = adt_i2c;
|
||||
else if (funcs & (I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
ret = adt_smbus;
|
||||
else
|
||||
ret = adt_dummy;
|
||||
|
||||
close(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Remove trailing spaces from a string
|
||||
Return the new string length including the trailing NUL */
|
||||
static int rtrim(char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = strlen(s) - 1; i >= 0 && (s[i] == ' ' || s[i] == '\n'); i--)
|
||||
s[i] = '\0';
|
||||
return i + 2;
|
||||
}
|
||||
|
||||
void free_adapters(struct i2c_adap *adapters)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; adapters[i].name; i++)
|
||||
free(adapters[i].name);
|
||||
free(adapters);
|
||||
}
|
||||
|
||||
/* We allocate space for the adapters in bunches. The last item is a
|
||||
terminator, so here we start with room for 7 adapters, which should
|
||||
be enough in most cases. If not, we allocate more later as needed. */
|
||||
#define BUNCH 8
|
||||
|
||||
/* n must match the size of adapters at calling time */
|
||||
static struct i2c_adap *more_adapters(struct i2c_adap *adapters, int n)
|
||||
{
|
||||
struct i2c_adap *new_adapters;
|
||||
|
||||
new_adapters = realloc(adapters, (n + BUNCH) * sizeof(struct i2c_adap));
|
||||
if (!new_adapters) {
|
||||
free_adapters(adapters);
|
||||
return NULL;
|
||||
}
|
||||
memset(new_adapters + n, 0, BUNCH * sizeof(struct i2c_adap));
|
||||
|
||||
return new_adapters;
|
||||
}
|
||||
|
||||
struct i2c_adap *gather_i2c_busses(void)
|
||||
{
|
||||
char s[120];
|
||||
struct dirent *de, *dde;
|
||||
DIR *dir, *ddir;
|
||||
FILE *f;
|
||||
char fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX];
|
||||
int foundsysfs = 0;
|
||||
int count=0;
|
||||
struct i2c_adap *adapters;
|
||||
|
||||
adapters = calloc(BUNCH, sizeof(struct i2c_adap));
|
||||
if (!adapters)
|
||||
return NULL;
|
||||
|
||||
/* look in /proc/bus/i2c */
|
||||
if ((f = fopen("/proc/bus/i2c", "r"))) {
|
||||
while (fgets(s, 120, f)) {
|
||||
char *algo, *name, *type, *all;
|
||||
int len_algo, len_name, len_type;
|
||||
int i2cbus;
|
||||
|
||||
algo = strrchr(s, '\t');
|
||||
*(algo++) = '\0';
|
||||
len_algo = rtrim(algo);
|
||||
|
||||
name = strrchr(s, '\t');
|
||||
*(name++) = '\0';
|
||||
len_name = rtrim(name);
|
||||
|
||||
type = strrchr(s, '\t');
|
||||
*(type++) = '\0';
|
||||
len_type = rtrim(type);
|
||||
|
||||
sscanf(s, "i2c-%d", &i2cbus);
|
||||
|
||||
if ((count + 1) % BUNCH == 0) {
|
||||
/* We need more space */
|
||||
adapters = more_adapters(adapters, count + 1);
|
||||
if (!adapters)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
all = malloc(len_name + len_type + len_algo);
|
||||
if (all == NULL) {
|
||||
free_adapters(adapters);
|
||||
return NULL;
|
||||
}
|
||||
adapters[count].nr = i2cbus;
|
||||
adapters[count].name = strcpy(all, name);
|
||||
adapters[count].funcs = strcpy(all + len_name, type);
|
||||
adapters[count].algo = strcpy(all + len_name + len_type,
|
||||
algo);
|
||||
count++;
|
||||
}
|
||||
fclose(f);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* look in sysfs */
|
||||
/* First figure out where sysfs was mounted */
|
||||
if ((f = fopen("/proc/mounts", "r")) == NULL) {
|
||||
goto done;
|
||||
}
|
||||
while (fgets(n, NAME_MAX, f)) {
|
||||
sscanf(n, "%*[^ ] %[^ ] %[^ ] %*s\n", sysfs, fstype);
|
||||
if (strcasecmp(fstype, "sysfs") == 0) {
|
||||
foundsysfs++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (! foundsysfs) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Bus numbers in i2c-adapter don't necessarily match those in
|
||||
i2c-dev and what we really care about are the i2c-dev numbers.
|
||||
Unfortunately the names are harder to get in i2c-dev */
|
||||
strcat(sysfs, "/class/i2c-dev");
|
||||
if(!(dir = opendir(sysfs)))
|
||||
goto done;
|
||||
/* go through the busses */
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (!strcmp(de->d_name, "."))
|
||||
continue;
|
||||
if (!strcmp(de->d_name, ".."))
|
||||
continue;
|
||||
|
||||
/* this should work for kernels 2.6.5 or higher and */
|
||||
/* is preferred because is unambiguous */
|
||||
sprintf(n, "%s/%s/name", sysfs, de->d_name);
|
||||
f = fopen(n, "r");
|
||||
/* this seems to work for ISA */
|
||||
if(f == NULL) {
|
||||
sprintf(n, "%s/%s/device/name", sysfs, de->d_name);
|
||||
f = fopen(n, "r");
|
||||
}
|
||||
/* non-ISA is much harder */
|
||||
/* and this won't find the correct bus name if a driver
|
||||
has more than one bus */
|
||||
if(f == NULL) {
|
||||
sprintf(n, "%s/%s/device", sysfs, de->d_name);
|
||||
if(!(ddir = opendir(n)))
|
||||
continue;
|
||||
while ((dde = readdir(ddir)) != NULL) {
|
||||
if (!strcmp(dde->d_name, "."))
|
||||
continue;
|
||||
if (!strcmp(dde->d_name, ".."))
|
||||
continue;
|
||||
if ((!strncmp(dde->d_name, "i2c-", 4))) {
|
||||
sprintf(n, "%s/%s/device/%s/name",
|
||||
sysfs, de->d_name, dde->d_name);
|
||||
if((f = fopen(n, "r")))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
if (f != NULL) {
|
||||
int i2cbus;
|
||||
enum adt type;
|
||||
char *px;
|
||||
|
||||
px = fgets(s, 120, f);
|
||||
fclose(f);
|
||||
if (!px) {
|
||||
fprintf(stderr, "%s: read error\n", n);
|
||||
continue;
|
||||
}
|
||||
if ((px = strchr(s, '\n')) != NULL)
|
||||
*px = 0;
|
||||
if (!sscanf(de->d_name, "i2c-%d", &i2cbus))
|
||||
continue;
|
||||
if (!strncmp(s, "ISA ", 4)) {
|
||||
type = adt_isa;
|
||||
} else {
|
||||
/* Attempt to probe for adapter capabilities */
|
||||
type = i2c_get_funcs(i2cbus);
|
||||
}
|
||||
|
||||
if ((count + 1) % BUNCH == 0) {
|
||||
/* We need more space */
|
||||
adapters = more_adapters(adapters, count + 1);
|
||||
if (!adapters)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
adapters[count].nr = i2cbus;
|
||||
adapters[count].name = strdup(s);
|
||||
if (adapters[count].name == NULL) {
|
||||
free_adapters(adapters);
|
||||
return NULL;
|
||||
}
|
||||
adapters[count].funcs = adap_types[type].funcs;
|
||||
adapters[count].algo = adap_types[type].algo;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
done:
|
||||
return adapters;
|
||||
}
|
||||
|
||||
static int lookup_i2c_bus_by_name(const char *bus_name)
|
||||
{
|
||||
struct i2c_adap *adapters;
|
||||
int i, i2cbus = -1;
|
||||
|
||||
adapters = gather_i2c_busses();
|
||||
if (adapters == NULL) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Walk the list of i2c busses, looking for the one with the
|
||||
right name */
|
||||
for (i = 0; adapters[i].name; i++) {
|
||||
if (strcmp(adapters[i].name, bus_name) == 0) {
|
||||
if (i2cbus >= 0) {
|
||||
fprintf(stderr,
|
||||
"Error: I2C bus name is not unique!\n");
|
||||
i2cbus = -4;
|
||||
goto done;
|
||||
}
|
||||
i2cbus = adapters[i].nr;
|
||||
}
|
||||
}
|
||||
|
||||
if (i2cbus == -1)
|
||||
fprintf(stderr, "Error: I2C bus name doesn't match any "
|
||||
"bus present!\n");
|
||||
|
||||
done:
|
||||
free_adapters(adapters);
|
||||
return i2cbus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an I2CBUS command line argument and return the corresponding
|
||||
* bus number, or a negative value if the bus is invalid.
|
||||
*/
|
||||
int lookup_i2c_bus(const char *i2cbus_arg)
|
||||
{
|
||||
unsigned long i2cbus;
|
||||
char *end;
|
||||
|
||||
i2cbus = strtoul(i2cbus_arg, &end, 0);
|
||||
if (*end || !*i2cbus_arg) {
|
||||
/* Not a number, maybe a name? */
|
||||
return lookup_i2c_bus_by_name(i2cbus_arg);
|
||||
}
|
||||
if (i2cbus > 0xFFFFF) {
|
||||
fprintf(stderr, "Error: I2C bus out of range!\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
return i2cbus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a CHIP-ADDRESS command line argument and return the corresponding
|
||||
* chip address, or a negative value if the address is invalid.
|
||||
*/
|
||||
int parse_i2c_address(const char *address_arg)
|
||||
{
|
||||
long address;
|
||||
char *end;
|
||||
|
||||
address = strtol(address_arg, &end, 0);
|
||||
if (*end || !*address_arg) {
|
||||
fprintf(stderr, "Error: Chip address is not a number!\n");
|
||||
return -1;
|
||||
}
|
||||
if (address < 0x03 || address > 0x77) {
|
||||
fprintf(stderr, "Error: Chip address out of range "
|
||||
"(0x03-0x77)!\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
|
||||
{
|
||||
int file;
|
||||
|
||||
snprintf(filename, size, "/dev/i2c/%d", i2cbus);
|
||||
filename[size - 1] = '\0';
|
||||
file = open(filename, O_RDWR);
|
||||
|
||||
if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
sprintf(filename, "/dev/i2c-%d", i2cbus);
|
||||
file = open(filename, O_RDWR);
|
||||
}
|
||||
|
||||
if (file < 0 && !quiet) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stderr, "Error: Could not open file "
|
||||
"`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
|
||||
i2cbus, i2cbus, strerror(ENOENT));
|
||||
} else {
|
||||
fprintf(stderr, "Error: Could not open file "
|
||||
"`%s': %s\n", filename, strerror(errno));
|
||||
if (errno == EACCES)
|
||||
fprintf(stderr, "Run as root?\n");
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
int set_slave_addr(int file, int address, int force)
|
||||
{
|
||||
/* With force, let the user read from/write to the registers
|
||||
even when a driver is also running */
|
||||
if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) {
|
||||
fprintf(stderr,
|
||||
"Error: Could not set address to 0x%02x: %s\n",
|
||||
address, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
44
Script/i2c-tools-3.1.0/tools/i2cbusses.h
Normal file
44
Script/i2c-tools-3.1.0/tools/i2cbusses.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
i2cbusses.h - Part of the i2c-tools package
|
||||
|
||||
Copyright (C) 2004-2010 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.
|
||||
*/
|
||||
|
||||
#ifndef _I2CBUSSES_H
|
||||
#define _I2CBUSSES_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
struct i2c_adap {
|
||||
int nr;
|
||||
char *name;
|
||||
const char *funcs;
|
||||
const char *algo;
|
||||
};
|
||||
|
||||
struct i2c_adap *gather_i2c_busses(void);
|
||||
void free_adapters(struct i2c_adap *adapters);
|
||||
|
||||
int lookup_i2c_bus(const char *i2cbus_arg);
|
||||
int parse_i2c_address(const char *address_arg);
|
||||
int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet);
|
||||
int set_slave_addr(int file, int address, int force);
|
||||
|
||||
#define MISSING_FUNC_FMT "Error: Adapter does not have %s capability\n"
|
||||
|
||||
#endif
|
||||
87
Script/i2c-tools-3.1.0/tools/i2cdetect.8
Normal file
87
Script/i2c-tools-3.1.0/tools/i2cdetect.8
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
.TH I2CDETECT 8 "April 2008"
|
||||
.SH NAME
|
||||
i2cdetect \- detect I2C chips
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B i2cdetect
|
||||
.RI [ -y ]
|
||||
.RI [ -a ]
|
||||
.RI [ -q | -r ]
|
||||
.I i2cbus
|
||||
.RI [ "first last" ]
|
||||
.br
|
||||
.B i2cdetect
|
||||
.I -F
|
||||
.I i2cbus
|
||||
.br
|
||||
.B i2cdetect
|
||||
.I -V
|
||||
.br
|
||||
.B i2cdetect
|
||||
.I -l
|
||||
|
||||
.SH DESCRIPTION
|
||||
i2cdetect is a userspace program to scan an I2C bus for devices. It
|
||||
outputs a table with the list of detected devices on the specified bus.
|
||||
\fIi2cbus\fR indicates the number or name of the I2C bus to be scanned, and
|
||||
should correspond to one of the busses listed by \fIi2cdetect -l\fR.
|
||||
The optional parameters \fIfirst\fR and \fIlast\fR restrict the scanning
|
||||
range (default: from 0x03 to 0x77).
|
||||
.PP
|
||||
i2cdetect can also be used to query the functionalities of an I2C bus
|
||||
(see option \fB-F\fP.)
|
||||
|
||||
.SH WARNING
|
||||
This program can confuse your I2C bus, cause data loss and worse!
|
||||
|
||||
.SH INTERPRETING THE OUTPUT
|
||||
Each cell in the output table will contain one of the following symbols:
|
||||
.IP \(bu "\w'\(bu'u+1n"
|
||||
"--". The address was probed but no chip answered.
|
||||
.IP \(bu
|
||||
"UU". Probing was skipped, because this address is currently in use by
|
||||
a driver. This strongly suggests that there is a chip at this address.
|
||||
.IP \(bu
|
||||
An address number in hexadecimal, e.g. "2d" or "4e". A chip
|
||||
was found at this address.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B "\-y"
|
||||
Disable interactive mode. By default, i2cdetect will wait for a confirmation
|
||||
from the user before messing with the I2C bus. When this flag is used, it
|
||||
will perform the operation directly. This is mainly meant to be used in
|
||||
scripts.
|
||||
.TP
|
||||
.B "\-a"
|
||||
Force scanning of non-regular addresses. Not recommended.
|
||||
.TP
|
||||
.B "\-q"
|
||||
Use SMBus "quick write" commands for probing (by default, the command
|
||||
used is the one believed to be the safest for each address).
|
||||
Not recommended. This is known to corrupt the Atmel AT24RF08 EEPROM
|
||||
found on many IBM Thinkpad laptops.
|
||||
.TP
|
||||
.B "\-r"
|
||||
Use SMBus "read byte" commands for probing (by default, the command
|
||||
used is the one believed to be the safest for each address).
|
||||
Not recommended. This is known to lock SMBus on various write-only
|
||||
chips (most notably clock chips at address 0x69).
|
||||
.TP
|
||||
.B "\-F"
|
||||
Display the list of functionalities implemented by the adapter and exit.
|
||||
.TP
|
||||
.B "\-V"
|
||||
Display the version and exit.
|
||||
.TP
|
||||
.B "\-l"
|
||||
Output a list of installed busses.
|
||||
|
||||
.SH SEE ALSO
|
||||
i2cdump(8), sensors-detect(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Frodo Looijaard, Mark D. Studebaker and Jean Delvare
|
||||
|
||||
This manual page was originally written by Aurelien Jarno
|
||||
<aurel32@debian.org>, for the Debian GNU/Linux system.
|
||||
357
Script/i2c-tools-3.1.0/tools/i2cdetect.c
Normal file
357
Script/i2c-tools-3.1.0/tools/i2cdetect.c
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
i2cdetect.c - a user-space program to scan for I2C devices
|
||||
Copyright (C) 1999-2004 Frodo Looijaard <frodol@dds.nl>, and
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2004-2010 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include "i2cbusses.h"
|
||||
#include "../version.h"
|
||||
|
||||
#define MODE_AUTO 0
|
||||
#define MODE_QUICK 1
|
||||
#define MODE_READ 2
|
||||
#define MODE_FUNC 3
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]\n"
|
||||
" i2cdetect -F I2CBUS\n"
|
||||
" i2cdetect -l\n"
|
||||
" I2CBUS is an integer or an I2C bus name\n"
|
||||
" If provided, FIRST and LAST limit the probing range.\n");
|
||||
}
|
||||
|
||||
static int scan_i2c_bus(int file, int mode, int first, int last)
|
||||
{
|
||||
int i, j;
|
||||
int res;
|
||||
|
||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
|
||||
|
||||
for (i = 0; i < 128; i += 16) {
|
||||
printf("%02x: ", i);
|
||||
for(j = 0; j < 16; j++) {
|
||||
fflush(stdout);
|
||||
|
||||
/* Skip unwanted addresses */
|
||||
if (i+j < first || i+j > last) {
|
||||
printf(" ");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set slave address */
|
||||
if (ioctl(file, I2C_SLAVE, i+j) < 0) {
|
||||
if (errno == EBUSY) {
|
||||
printf("UU ");
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr, "Error: Could not set "
|
||||
"address to 0x%02x: %s\n", i+j,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Probe this address */
|
||||
switch (mode) {
|
||||
case MODE_QUICK:
|
||||
/* This is known to corrupt the Atmel AT24RF08
|
||||
EEPROM */
|
||||
res = i2c_smbus_write_quick(file,
|
||||
I2C_SMBUS_WRITE);
|
||||
break;
|
||||
case MODE_READ:
|
||||
/* This is known to lock SMBus on various
|
||||
write-only chips (mainly clock chips) */
|
||||
res = i2c_smbus_read_byte(file);
|
||||
break;
|
||||
default:
|
||||
if ((i+j >= 0x30 && i+j <= 0x37)
|
||||
|| (i+j >= 0x50 && i+j <= 0x5F))
|
||||
res = i2c_smbus_read_byte(file);
|
||||
else
|
||||
res = i2c_smbus_write_quick(file,
|
||||
I2C_SMBUS_WRITE);
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
printf("-- ");
|
||||
else
|
||||
printf("%02x ", i+j);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct func
|
||||
{
|
||||
long value;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
static const struct func all_func[] = {
|
||||
{ .value = I2C_FUNC_I2C,
|
||||
.name = "I2C" },
|
||||
{ .value = I2C_FUNC_SMBUS_QUICK,
|
||||
.name = "SMBus Quick Command" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_BYTE,
|
||||
.name = "SMBus Send Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_BYTE,
|
||||
.name = "SMBus Receive Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
|
||||
.name = "SMBus Write Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_BYTE_DATA,
|
||||
.name = "SMBus Read Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA,
|
||||
.name = "SMBus Write Word" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_WORD_DATA,
|
||||
.name = "SMBus Read Word" },
|
||||
{ .value = I2C_FUNC_SMBUS_PROC_CALL,
|
||||
.name = "SMBus Process Call" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
|
||||
.name = "SMBus Block Write" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA,
|
||||
.name = "SMBus Block Read" },
|
||||
{ .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL,
|
||||
.name = "SMBus Block Process Call" },
|
||||
{ .value = I2C_FUNC_SMBUS_PEC,
|
||||
.name = "SMBus PEC" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
|
||||
.name = "I2C Block Write" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK,
|
||||
.name = "I2C Block Read" },
|
||||
{ .value = 0, .name = "" }
|
||||
};
|
||||
|
||||
static void print_functionality(unsigned long funcs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; all_func[i].value; i++) {
|
||||
printf("%-32s %s\n", all_func[i].name,
|
||||
(funcs & all_func[i].value) ? "yes" : "no");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the installed i2c busses. The format is those of Linux 2.4's
|
||||
* /proc/bus/i2c for historical compatibility reasons.
|
||||
*/
|
||||
static void print_i2c_busses(void)
|
||||
{
|
||||
struct i2c_adap *adapters;
|
||||
int count;
|
||||
|
||||
adapters = gather_i2c_busses();
|
||||
if (adapters == NULL) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (count = 0; adapters[count].name; count++) {
|
||||
printf("i2c-%d\t%-10s\t%-32s\t%s\n",
|
||||
adapters[count].nr, adapters[count].funcs,
|
||||
adapters[count].name, adapters[count].algo);
|
||||
}
|
||||
|
||||
free_adapters(adapters);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *end;
|
||||
int i2cbus, file, res;
|
||||
char filename[20];
|
||||
unsigned long funcs;
|
||||
int mode = MODE_AUTO;
|
||||
int first = 0x03, last = 0x77;
|
||||
int flags = 0;
|
||||
int yes = 0, version = 0, list = 0;
|
||||
|
||||
/* handle (optional) flags first */
|
||||
while (1+flags < argc && argv[1+flags][0] == '-') {
|
||||
switch (argv[1+flags][1]) {
|
||||
case 'V': version = 1; break;
|
||||
case 'y': yes = 1; break;
|
||||
case 'l': list = 1; break;
|
||||
case 'F':
|
||||
if (mode != MODE_AUTO && mode != MODE_FUNC) {
|
||||
fprintf(stderr, "Error: Different modes "
|
||||
"specified!\n");
|
||||
exit(1);
|
||||
}
|
||||
mode = MODE_FUNC;
|
||||
break;
|
||||
case 'r':
|
||||
if (mode == MODE_QUICK) {
|
||||
fprintf(stderr, "Error: Different modes "
|
||||
"specified!\n");
|
||||
exit(1);
|
||||
}
|
||||
mode = MODE_READ;
|
||||
break;
|
||||
case 'q':
|
||||
if (mode == MODE_READ) {
|
||||
fprintf(stderr, "Error: Different modes "
|
||||
"specified!\n");
|
||||
exit(1);
|
||||
}
|
||||
mode = MODE_QUICK;
|
||||
break;
|
||||
case 'a':
|
||||
first = 0x00;
|
||||
last = 0x7F;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Unsupported option "
|
||||
"\"%s\"!\n", argv[1+flags]);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
|
||||
if (version) {
|
||||
fprintf(stderr, "i2cdetect version %s\n", VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (list) {
|
||||
print_i2c_busses();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc < flags + 2) {
|
||||
fprintf(stderr, "Error: No i2c-bus specified!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
i2cbus = lookup_i2c_bus(argv[flags+1]);
|
||||
if (i2cbus < 0) {
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* read address range if present */
|
||||
if (argc == flags + 4 && mode != MODE_FUNC) {
|
||||
int tmp;
|
||||
|
||||
tmp = strtol(argv[flags+2], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: FIRST argment not a "
|
||||
"number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (tmp < first || tmp > last) {
|
||||
fprintf(stderr, "Error: FIRST argument out of range "
|
||||
"(0x%02x-0x%02x)!\n", first, last);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
first = tmp;
|
||||
|
||||
tmp = strtol(argv[flags+3], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: LAST argment not a "
|
||||
"number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (tmp < first || tmp > last) {
|
||||
fprintf(stderr, "Error: LAST argument out of range "
|
||||
"(0x%02x-0x%02x)!\n", first, last);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
last = tmp;
|
||||
} else if (argc != flags + 2) {
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
|
||||
if (file < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||
fprintf(stderr, "Error: Could not get the adapter "
|
||||
"functionality matrix: %s\n", strerror(errno));
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Special case, we only list the implemented functionalities */
|
||||
if (mode == MODE_FUNC) {
|
||||
close(file);
|
||||
printf("Functionalities implemented by %s:\n", filename);
|
||||
print_functionality(funcs);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (mode != MODE_READ && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
|
||||
fprintf(stderr, "Error: Can't use SMBus Quick Write command "
|
||||
"on this bus\n");
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
if (mode != MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
|
||||
fprintf(stderr, "Error: Can't use SMBus Read Byte command "
|
||||
"on this bus\n");
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!yes) {
|
||||
char s[2];
|
||||
|
||||
fprintf(stderr, "WARNING! This program can confuse your I2C "
|
||||
"bus, cause data loss and worse!\n");
|
||||
|
||||
fprintf(stderr, "I will probe file %s%s.\n", filename,
|
||||
mode==MODE_QUICK?" using quick write commands":
|
||||
mode==MODE_READ?" using read byte commands":"");
|
||||
fprintf(stderr, "I will probe address range 0x%02x-0x%02x.\n",
|
||||
first, last);
|
||||
|
||||
fprintf(stderr, "Continue? [Y/n] ");
|
||||
fflush(stderr);
|
||||
if (!fgets(s, 2, stdin)
|
||||
|| (s[0] != '\n' && s[0] != 'y' && s[0] != 'Y')) {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
res = scan_i2c_bus(file, mode, first, last);
|
||||
|
||||
close(file);
|
||||
|
||||
exit(res?1:0);
|
||||
}
|
||||
84
Script/i2c-tools-3.1.0/tools/i2cdump.8
Normal file
84
Script/i2c-tools-3.1.0/tools/i2cdump.8
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
.TH I2CDUMP 8 "May 2008"
|
||||
.SH NAME
|
||||
i2cdump \- examine I2C registers
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B i2cdump
|
||||
.RB [ -f ]
|
||||
.RB [ "-r first-last" ]
|
||||
.RB [ -y ]
|
||||
.I i2cbus
|
||||
.I address
|
||||
.RI [ "mode " [ "bank " [ bankreg ]]]
|
||||
.br
|
||||
.B i2cdump
|
||||
.B -V
|
||||
|
||||
.SH DESCRIPTION
|
||||
i2cdump is a small helper program to examine registers
|
||||
visible through the I2C bus.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B -V
|
||||
Display the version and exit.
|
||||
.TP
|
||||
.B -f
|
||||
Force access to the device even if it is already busy. By default, i2cdump
|
||||
will refuse to access a device which is already under the control of a
|
||||
kernel driver. Using this flag is dangerous, it can seriously confuse the
|
||||
kernel driver in question. It can also cause i2cdump to return invalid
|
||||
results. So use at your own risk and only if you know what you're doing.
|
||||
.TP
|
||||
.B -r first-last
|
||||
Limit the range of registers being accessed. This option is only available
|
||||
with modes \fBb\fP, \fBw\fP, \fBc\fP and \fBW\fP. For mode \fBW\fP,
|
||||
\fBfirst\fR must be even and \fBlast\fR must be odd.
|
||||
.TP
|
||||
.B -y
|
||||
Disable interactive mode. By default, i2cdump will wait for a confirmation
|
||||
from the user before messing with the I2C bus. When this flag is used, it
|
||||
will perform the operation directly. This is mainly meant to be used in
|
||||
scripts.
|
||||
.PP
|
||||
At least two options must be provided to i2cdump. \fIi2cbus\fR indicates the
|
||||
number or name of the I2C bus to be scanned. This number should correspond to one
|
||||
of the busses listed by \fIi2cdetect -l\fR. \fIaddress\fR indicates the
|
||||
address to be scanned on that bus, and is an integer between 0x03 and 0x77.
|
||||
.PP
|
||||
The \fImode\fR parameter, if specified, is one of the letters \fBb\fP, \fBw\fP,
|
||||
\fBs\fP, or \fBi\fP, corresponding to a read size of a single byte, a 16-bit
|
||||
word, an SMBus block, an I2C block, respectively. The \fBc\fP mode is a
|
||||
little different, it reads all bytes consecutively, and is useful for chips that
|
||||
have an address auto-increment feature, such as EEPROMs. The \fBW\fP mode is
|
||||
also special, it is similar to \fBw\fP except that a read command will only
|
||||
be issued on even register addresses; this is again mainly useful for EEPROMs.
|
||||
.PP
|
||||
A \fBp\fP can also be appended to the \fImode\fR parameter (except for
|
||||
\fBi\fP and \fBW\fP) to enable PEC. If the \fImode\fR parameter is omitted,
|
||||
i2cdump defaults to byte access without PEC.
|
||||
.PP
|
||||
The \fIbank\fR and \fIbankreg\fR parameters are useful on the W83781D and
|
||||
similar chips (at the time of writing, all Winbond and Asus chips).
|
||||
\fIbank\fR is an integer between 0 and 7, and \fIbankreg\fR is an integer
|
||||
between 0x00 and 0xFF (default value: 0x4E). The W83781D data sheet has more
|
||||
information on bank selection.
|
||||
|
||||
.SH WARNING
|
||||
i2cdump can be dangerous if used improperly. Most notably, the \fBc\fP mode
|
||||
starts with WRITING a byte to the chip. On most chips it will be stored in the
|
||||
address pointer register, which is OK, but some chips with a single register
|
||||
or no (visible) register at all will most likely see this as a real WRITE,
|
||||
resulting in possible misbehavior or corruption. Do not use i2cdump
|
||||
on random addresses. Anyway, it is of little use unless you have good
|
||||
knowledge of the chip you're working with and an idea of what you are looking
|
||||
for.
|
||||
|
||||
.SH SEE ALSO
|
||||
i2cset(8), i2cdetect(8), isadump(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Frodo Looijaard, Mark D. Studebaker and Jean Delvare
|
||||
|
||||
This manual page was originally written by David Z Maze <dmaze@debian.org> for
|
||||
the Debian GNU/Linux system.
|
||||
487
Script/i2c-tools-3.1.0/tools/i2cdump.c
Normal file
487
Script/i2c-tools-3.1.0/tools/i2cdump.c
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
i2cdump.c - a user-space program to dump I2C registers
|
||||
Copyright (C) 2002-2003 Frodo Looijaard <frodol@dds.nl>, and
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2004-2010 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include "i2cbusses.h"
|
||||
#include "util.h"
|
||||
#include "../version.h"
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: i2cdump [-f] [-y] [-r first-last] I2CBUS ADDRESS [MODE [BANK [BANKREG]]]\n"
|
||||
" I2CBUS is an integer or an I2C bus name\n"
|
||||
" ADDRESS is an integer (0x03 - 0x77)\n"
|
||||
" MODE is one of:\n"
|
||||
" b (byte, default)\n"
|
||||
" w (word)\n"
|
||||
" W (word on even register addresses)\n"
|
||||
" s (SMBus block)\n"
|
||||
" i (I2C block)\n"
|
||||
" c (consecutive byte)\n"
|
||||
" Append p for SMBus PEC\n");
|
||||
}
|
||||
|
||||
static int check_funcs(int file, int size, int pec)
|
||||
{
|
||||
unsigned long funcs;
|
||||
|
||||
/* check adapter functionality */
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||
fprintf(stderr, "Error: Could not get the adapter "
|
||||
"functionality matrix: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus receive byte");
|
||||
return -1;
|
||||
}
|
||||
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus read byte");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus read word");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus block read");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "I2C block read");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pec
|
||||
&& !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C))) {
|
||||
fprintf(stderr, "Warning: Adapter does "
|
||||
"not seem to support PEC\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *end;
|
||||
int i, j, res, i2cbus, address, size, file;
|
||||
int bank = 0, bankreg = 0x4E, old_bank = 0;
|
||||
char filename[20];
|
||||
int block[256], s_length = 0;
|
||||
int pec = 0, even = 0;
|
||||
int flags = 0;
|
||||
int force = 0, yes = 0, version = 0;
|
||||
const char *range = NULL;
|
||||
int first = 0x00, last = 0xff;
|
||||
|
||||
/* handle (optional) flags first */
|
||||
while (1+flags < argc && argv[1+flags][0] == '-') {
|
||||
switch (argv[1+flags][1]) {
|
||||
case 'V': version = 1; break;
|
||||
case 'f': force = 1; break;
|
||||
case 'r': range = argv[1+(++flags)]; break;
|
||||
case 'y': yes = 1; break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Unsupported option "
|
||||
"\"%s\"!\n", argv[1+flags]);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
|
||||
if (version) {
|
||||
fprintf(stderr, "i2cdump version %s\n", VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc < flags + 2) {
|
||||
fprintf(stderr, "Error: No i2c-bus specified!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
i2cbus = lookup_i2c_bus(argv[flags+1]);
|
||||
if (i2cbus < 0) {
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc < flags + 3) {
|
||||
fprintf(stderr, "Error: No address specified!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
address = parse_i2c_address(argv[flags+2]);
|
||||
if (address < 0) {
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc < flags + 4) {
|
||||
fprintf(stderr, "No size specified (using byte-data access)\n");
|
||||
size = I2C_SMBUS_BYTE_DATA;
|
||||
} else if (!strncmp(argv[flags+3], "b", 1)) {
|
||||
size = I2C_SMBUS_BYTE_DATA;
|
||||
pec = argv[flags+3][1] == 'p';
|
||||
} else if (!strncmp(argv[flags+3], "w", 1)) {
|
||||
size = I2C_SMBUS_WORD_DATA;
|
||||
pec = argv[flags+3][1] == 'p';
|
||||
} else if (!strncmp(argv[flags+3], "W", 1)) {
|
||||
size = I2C_SMBUS_WORD_DATA;
|
||||
even = 1;
|
||||
} else if (!strncmp(argv[flags+3], "s", 1)) {
|
||||
size = I2C_SMBUS_BLOCK_DATA;
|
||||
pec = argv[flags+3][1] == 'p';
|
||||
} else if (!strncmp(argv[flags+3], "c", 1)) {
|
||||
size = I2C_SMBUS_BYTE;
|
||||
pec = argv[flags+3][1] == 'p';
|
||||
} else if (!strcmp(argv[flags+3], "i"))
|
||||
size = I2C_SMBUS_I2C_BLOCK_DATA;
|
||||
else {
|
||||
fprintf(stderr, "Error: Invalid mode!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc > flags + 4) {
|
||||
bank = strtol(argv[flags+4], &end, 0);
|
||||
if (*end || size == I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
fprintf(stderr, "Error: Invalid bank number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if ((size == I2C_SMBUS_BYTE_DATA || size == I2C_SMBUS_WORD_DATA)
|
||||
&& (bank < 0 || bank > 15)) {
|
||||
fprintf(stderr, "Error: bank out of range!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (size == I2C_SMBUS_BLOCK_DATA
|
||||
&& (bank < 0 || bank > 0xff)) {
|
||||
fprintf(stderr, "Error: block command out of range!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc > flags + 5) {
|
||||
bankreg = strtol(argv[flags+5], &end, 0);
|
||||
if (*end || size == I2C_SMBUS_BLOCK_DATA) {
|
||||
fprintf(stderr, "Error: Invalid bank register "
|
||||
"number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (bankreg < 0 || bankreg > 0xff) {
|
||||
fprintf(stderr, "Error: bank out of range "
|
||||
"(0-0xff)!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse optional range string */
|
||||
if (range) {
|
||||
char *dash;
|
||||
|
||||
first = strtol(range, &dash, 0);
|
||||
if (dash == range || *dash != '-'
|
||||
|| first < 0 || first > 0xff) {
|
||||
fprintf(stderr, "Error: Invalid range parameter!\n");
|
||||
exit(1);
|
||||
}
|
||||
last = strtol(++dash, &end, 0);
|
||||
if (end == dash || *end != '\0'
|
||||
|| last < first || last > 0xff) {
|
||||
fprintf(stderr, "Error: Invalid range parameter!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check mode constraints */
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
if (!even || (!(first%2) && last%2))
|
||||
break;
|
||||
/* Fall through */
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"Error: Range parameter not compatible with selected mode!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
|
||||
if (file < 0
|
||||
|| check_funcs(file, size, pec)
|
||||
|| set_slave_addr(file, address, force))
|
||||
exit(1);
|
||||
|
||||
if (pec) {
|
||||
if (ioctl(file, I2C_PEC, 1) < 0) {
|
||||
fprintf(stderr, "Error: Could not set PEC: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!yes) {
|
||||
fprintf(stderr, "WARNING! This program can confuse your I2C "
|
||||
"bus, cause data loss and worse!\n");
|
||||
|
||||
fprintf(stderr, "I will probe file %s, address 0x%x, mode "
|
||||
"%s\n", filename, address,
|
||||
size == I2C_SMBUS_BLOCK_DATA ? "smbus block" :
|
||||
size == I2C_SMBUS_I2C_BLOCK_DATA ? "i2c block" :
|
||||
size == I2C_SMBUS_BYTE ? "byte consecutive read" :
|
||||
size == I2C_SMBUS_BYTE_DATA ? "byte" : "word");
|
||||
if (pec)
|
||||
fprintf(stderr, "PEC checking enabled.\n");
|
||||
if (even)
|
||||
fprintf(stderr, "Only probing even register "
|
||||
"addresses.\n");
|
||||
if (bank) {
|
||||
if (size == I2C_SMBUS_BLOCK_DATA)
|
||||
fprintf(stderr, "Using command 0x%02x.\n",
|
||||
bank);
|
||||
else
|
||||
fprintf(stderr, "Probing bank %d using bank "
|
||||
"register 0x%02x.\n", bank, bankreg);
|
||||
}
|
||||
if (range) {
|
||||
fprintf(stderr,
|
||||
"Probe range limited to 0x%02x-0x%02x.\n",
|
||||
first, last);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Continue? [Y/n] ");
|
||||
fflush(stderr);
|
||||
if (!user_ack(1)) {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* See Winbond w83781d data sheet for bank details */
|
||||
if (bank && size != I2C_SMBUS_BLOCK_DATA) {
|
||||
res = i2c_smbus_read_byte_data(file, bankreg);
|
||||
if (res >= 0) {
|
||||
old_bank = res;
|
||||
res = i2c_smbus_write_byte_data(file, bankreg,
|
||||
bank | (old_bank & 0xf0));
|
||||
}
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error: Bank switching failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle all but word data */
|
||||
if (size != I2C_SMBUS_WORD_DATA || even) {
|
||||
/* do the block transaction */
|
||||
if (size == I2C_SMBUS_BLOCK_DATA
|
||||
|| size == I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
unsigned char cblock[288];
|
||||
|
||||
if (size == I2C_SMBUS_BLOCK_DATA) {
|
||||
res = i2c_smbus_read_block_data(file, bank,
|
||||
cblock);
|
||||
/* Remember returned block length for a nicer
|
||||
display later */
|
||||
s_length = res;
|
||||
} else {
|
||||
for (res = 0; res < 256; res += i) {
|
||||
i = i2c_smbus_read_i2c_block_data(file,
|
||||
res, 32, cblock + res);
|
||||
if (i <= 0) {
|
||||
res = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res <= 0) {
|
||||
fprintf(stderr, "Error: Block read failed, "
|
||||
"return code %d\n", res);
|
||||
exit(1);
|
||||
}
|
||||
if (res >= 256)
|
||||
res = 256;
|
||||
for (i = 0; i < res; i++)
|
||||
block[i] = cblock[i];
|
||||
if (size != I2C_SMBUS_BLOCK_DATA)
|
||||
for (i = res; i < 256; i++)
|
||||
block[i] = -1;
|
||||
}
|
||||
|
||||
if (size == I2C_SMBUS_BYTE) {
|
||||
res = i2c_smbus_write_byte(file, first);
|
||||
if(res != 0) {
|
||||
fprintf(stderr, "Error: Write start address "
|
||||
"failed, return code %d\n", res);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
|
||||
" 0123456789abcdef\n");
|
||||
for (i = 0; i < 256; i+=16) {
|
||||
if (size == I2C_SMBUS_BLOCK_DATA && i >= s_length)
|
||||
break;
|
||||
if (i/16 < first/16)
|
||||
continue;
|
||||
if (i/16 > last/16)
|
||||
break;
|
||||
|
||||
printf("%02x: ", i);
|
||||
for (j = 0; j < 16; j++) {
|
||||
fflush(stdout);
|
||||
/* Skip unwanted registers */
|
||||
if (i+j < first || i+j > last) {
|
||||
printf(" ");
|
||||
if (size == I2C_SMBUS_WORD_DATA) {
|
||||
printf(" ");
|
||||
j++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size == I2C_SMBUS_BYTE_DATA) {
|
||||
block[i+j] = res =
|
||||
i2c_smbus_read_byte_data(file, i+j);
|
||||
} else if (size == I2C_SMBUS_WORD_DATA) {
|
||||
res = i2c_smbus_read_word_data(file,
|
||||
i+j);
|
||||
if (res < 0) {
|
||||
block[i+j] = res;
|
||||
block[i+j+1] = res;
|
||||
} else {
|
||||
block[i+j] = res & 0xff;
|
||||
block[i+j+1] = res >> 8;
|
||||
}
|
||||
} else if (size == I2C_SMBUS_BYTE) {
|
||||
block[i+j] = res =
|
||||
i2c_smbus_read_byte(file);
|
||||
} else
|
||||
res = block[i+j];
|
||||
|
||||
if (size == I2C_SMBUS_BLOCK_DATA
|
||||
&& i+j >= s_length) {
|
||||
printf(" ");
|
||||
} else if (res < 0) {
|
||||
printf("XX ");
|
||||
if (size == I2C_SMBUS_WORD_DATA)
|
||||
printf("XX ");
|
||||
} else {
|
||||
printf("%02x ", block[i+j]);
|
||||
if (size == I2C_SMBUS_WORD_DATA)
|
||||
printf("%02x ", block[i+j+1]);
|
||||
}
|
||||
if (size == I2C_SMBUS_WORD_DATA)
|
||||
j++;
|
||||
}
|
||||
printf(" ");
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (size == I2C_SMBUS_BLOCK_DATA
|
||||
&& i+j >= s_length)
|
||||
break;
|
||||
/* Skip unwanted registers */
|
||||
if (i+j < first || i+j > last) {
|
||||
printf(" ");
|
||||
continue;
|
||||
}
|
||||
|
||||
res = block[i+j];
|
||||
if (res < 0)
|
||||
printf("X");
|
||||
else
|
||||
if ((res & 0xff) == 0x00
|
||||
|| (res & 0xff) == 0xff)
|
||||
printf(".");
|
||||
else
|
||||
if ((res & 0xff) < 32
|
||||
|| (res & 0xff) >= 127)
|
||||
printf("?");
|
||||
else
|
||||
printf("%c", res & 0xff);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n");
|
||||
for (i = 0; i < 256; i+=8) {
|
||||
if (i/8 < first/8)
|
||||
continue;
|
||||
if (i/8 > last/8)
|
||||
break;
|
||||
|
||||
printf("%02x: ", i);
|
||||
for (j = 0; j < 8; j++) {
|
||||
/* Skip unwanted registers */
|
||||
if (i+j < first || i+j > last) {
|
||||
printf(" ");
|
||||
continue;
|
||||
}
|
||||
|
||||
res = i2c_smbus_read_word_data(file, i+j);
|
||||
if (res < 0)
|
||||
printf("XXXX ");
|
||||
else
|
||||
printf("%04x ", res & 0xffff);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
if (bank && size != I2C_SMBUS_BLOCK_DATA) {
|
||||
i2c_smbus_write_byte_data(file, bankreg, old_bank);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
68
Script/i2c-tools-3.1.0/tools/i2cget.8
Normal file
68
Script/i2c-tools-3.1.0/tools/i2cget.8
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
.TH I2CGET 8 "May 2008"
|
||||
.SH "NAME"
|
||||
i2cget \- read from I2C/SMBus chip registers
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B i2cget
|
||||
.RB [ -f ]
|
||||
.RB [ -y ]
|
||||
.I i2cbus
|
||||
.I chip-address
|
||||
.RI [ "data-address " [ mode ]]
|
||||
.br
|
||||
.B i2cget
|
||||
.B -V
|
||||
|
||||
.SH DESCRIPTION
|
||||
i2cget is a small helper program to read registers visible through the I2C
|
||||
bus (or SMBus).
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B -V
|
||||
Display the version and exit.
|
||||
.TP
|
||||
.B -f
|
||||
Force access to the device even if it is already busy. By default, i2cget
|
||||
will refuse to access a device which is already under the control of a
|
||||
kernel driver. Using this flag is dangerous, it can seriously confuse the
|
||||
kernel driver in question. It can also cause i2cget to return an invalid
|
||||
value. So use at your own risk and only if you know what you're doing.
|
||||
.TP
|
||||
.B -y
|
||||
Disable interactive mode. By default, i2cget will wait for a confirmation
|
||||
from the user before messing with the I2C bus. When this flag is used, it
|
||||
will perform the operation directly. This is mainly meant to be used in
|
||||
scripts. Use with caution.
|
||||
.PP
|
||||
There are two required options to i2cget. \fIi2cbus\fR indicates the number
|
||||
or name of the I2C bus to be scanned. This number should correspond to one of
|
||||
the busses listed by \fIi2cdetect -l\fR. \fIchip-address\fR specifies the
|
||||
address of the chip on that bus, and is an integer between 0x03 and 0x77.
|
||||
.PP
|
||||
\fIdata-address\fR specifies the address on that chip to read from, and is
|
||||
an integer between 0x00 and 0xFF. If omitted, the currently active register
|
||||
will be read (if that makes sense for the considered chip).
|
||||
.PP
|
||||
The \fImode\fR parameter, if specified, is one of the letters \fBb\fP,
|
||||
\fBw\fP or \fBc\fP, corresponding to a read byte data, a read word data or a
|
||||
write byte/read byte transaction, respectively. A \fBp\fP can also be appended
|
||||
to the \fImode\fR parameter to enable PEC. If the \fImode\fR parameter is omitted,
|
||||
i2cget defaults to a read byte data transaction, unless \fIdata-address\fR is
|
||||
also omitted, in which case the default (and only valid) transaction is a
|
||||
single read byte.
|
||||
|
||||
.SH WARNING
|
||||
i2cget can be extremely dangerous if used improperly. I2C and SMBus are designed
|
||||
in such a way that an SMBus read transaction can be seen as a write transaction by
|
||||
certain chips. This is particularly true if setting \fImode\fR to \fBcp\fP (write byte/read
|
||||
byte with PEC). Be extremely careful using this program.
|
||||
|
||||
.SH SEE ALSO
|
||||
i2cdump(8), i2cset(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Jean Delvare
|
||||
|
||||
This manual page was strongly inspired from those written by David Z Maze
|
||||
for i2cset.
|
||||
256
Script/i2c-tools-3.1.0/tools/i2cget.c
Normal file
256
Script/i2c-tools-3.1.0/tools/i2cget.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
i2cget.c - A user-space program to read an I2C register.
|
||||
Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
Based on i2cset.c:
|
||||
Copyright (C) 2001-2003 Frodo Looijaard <frodol@dds.nl>, and
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2004-2005 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include "i2cbusses.h"
|
||||
#include "util.h"
|
||||
#include "../version.h"
|
||||
|
||||
static void help(void) __attribute__ ((noreturn));
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]\n"
|
||||
" I2CBUS is an integer or an I2C bus name\n"
|
||||
" ADDRESS is an integer (0x03 - 0x77)\n"
|
||||
" MODE is one of:\n"
|
||||
" b (read byte data, default)\n"
|
||||
" w (read word data)\n"
|
||||
" c (write byte/read byte)\n"
|
||||
" Append p for SMBus PEC\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int check_funcs(int file, int size, int daddress, int pec)
|
||||
{
|
||||
unsigned long funcs;
|
||||
|
||||
/* check adapter functionality */
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||
fprintf(stderr, "Error: Could not get the adapter "
|
||||
"functionality matrix: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus receive byte");
|
||||
return -1;
|
||||
}
|
||||
if (daddress >= 0
|
||||
&& !(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus read byte");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus read word");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pec
|
||||
&& !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C))) {
|
||||
fprintf(stderr, "Warning: Adapter does "
|
||||
"not seem to support PEC\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int confirm(const char *filename, int address, int size, int daddress,
|
||||
int pec)
|
||||
{
|
||||
int dont = 0;
|
||||
|
||||
fprintf(stderr, "WARNING! This program can confuse your I2C "
|
||||
"bus, cause data loss and worse!\n");
|
||||
|
||||
/* Don't let the user break his/her EEPROMs */
|
||||
if (address >= 0x50 && address <= 0x57 && pec) {
|
||||
fprintf(stderr, "STOP! EEPROMs are I2C devices, not "
|
||||
"SMBus devices. Using PEC\non I2C devices may "
|
||||
"result in unexpected results, such as\n"
|
||||
"trashing the contents of EEPROMs. We can't "
|
||||
"let you do that, sorry.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size == I2C_SMBUS_BYTE && daddress >= 0 && pec) {
|
||||
fprintf(stderr, "WARNING! All I2C chips and some SMBus chips "
|
||||
"will interpret a write\nbyte command with PEC as a"
|
||||
"write byte data command, effectively writing a\n"
|
||||
"value into a register!\n");
|
||||
dont++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "I will read from device file %s, chip "
|
||||
"address 0x%02x, ", filename, address);
|
||||
if (daddress < 0)
|
||||
fprintf(stderr, "current data\naddress");
|
||||
else
|
||||
fprintf(stderr, "data address\n0x%02x", daddress);
|
||||
fprintf(stderr, ", using %s.\n",
|
||||
size == I2C_SMBUS_BYTE ? (daddress < 0 ?
|
||||
"read byte" : "write byte/read byte") :
|
||||
size == I2C_SMBUS_BYTE_DATA ? "read byte data" :
|
||||
"read word data");
|
||||
if (pec)
|
||||
fprintf(stderr, "PEC checking enabled.\n");
|
||||
|
||||
fprintf(stderr, "Continue? [%s] ", dont ? "y/N" : "Y/n");
|
||||
fflush(stderr);
|
||||
if (!user_ack(!dont)) {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *end;
|
||||
int res, i2cbus, address, size, file;
|
||||
int daddress;
|
||||
char filename[20];
|
||||
int pec = 0;
|
||||
int flags = 0;
|
||||
int force = 0, yes = 0, version = 0;
|
||||
|
||||
/* handle (optional) flags first */
|
||||
while (1+flags < argc && argv[1+flags][0] == '-') {
|
||||
switch (argv[1+flags][1]) {
|
||||
case 'V': version = 1; break;
|
||||
case 'f': force = 1; break;
|
||||
case 'y': yes = 1; break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Unsupported option "
|
||||
"\"%s\"!\n", argv[1+flags]);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
|
||||
if (version) {
|
||||
fprintf(stderr, "i2cget version %s\n", VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc < flags + 3)
|
||||
help();
|
||||
|
||||
i2cbus = lookup_i2c_bus(argv[flags+1]);
|
||||
if (i2cbus < 0)
|
||||
help();
|
||||
|
||||
address = parse_i2c_address(argv[flags+2]);
|
||||
if (address < 0)
|
||||
help();
|
||||
|
||||
if (argc > flags + 3) {
|
||||
size = I2C_SMBUS_BYTE_DATA;
|
||||
daddress = strtol(argv[flags+3], &end, 0);
|
||||
if (*end || daddress < 0 || daddress > 0xff) {
|
||||
fprintf(stderr, "Error: Data address invalid!\n");
|
||||
help();
|
||||
}
|
||||
} else {
|
||||
size = I2C_SMBUS_BYTE;
|
||||
daddress = -1;
|
||||
}
|
||||
|
||||
if (argc > flags + 4) {
|
||||
switch (argv[flags+4][0]) {
|
||||
case 'b': size = I2C_SMBUS_BYTE_DATA; break;
|
||||
case 'w': size = I2C_SMBUS_WORD_DATA; break;
|
||||
case 'c': size = I2C_SMBUS_BYTE; break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Invalid mode!\n");
|
||||
help();
|
||||
}
|
||||
pec = argv[flags+4][1] == 'p';
|
||||
}
|
||||
|
||||
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
|
||||
if (file < 0
|
||||
|| check_funcs(file, size, daddress, pec)
|
||||
|| set_slave_addr(file, address, force))
|
||||
exit(1);
|
||||
|
||||
if (!yes && !confirm(filename, address, size, daddress, pec))
|
||||
exit(0);
|
||||
|
||||
if (pec && ioctl(file, I2C_PEC, 1) < 0) {
|
||||
fprintf(stderr, "Error: Could not set PEC: %s\n",
|
||||
strerror(errno));
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (daddress >= 0) {
|
||||
res = i2c_smbus_write_byte(file, daddress);
|
||||
if (res < 0)
|
||||
fprintf(stderr, "Warning - write failed\n");
|
||||
}
|
||||
res = i2c_smbus_read_byte(file);
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
res = i2c_smbus_read_word_data(file, daddress);
|
||||
break;
|
||||
default: /* I2C_SMBUS_BYTE_DATA */
|
||||
res = i2c_smbus_read_byte_data(file, daddress);
|
||||
}
|
||||
close(file);
|
||||
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error: Read failed\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
printf("0x%0*x\n", size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
102
Script/i2c-tools-3.1.0/tools/i2cset.8
Normal file
102
Script/i2c-tools-3.1.0/tools/i2cset.8
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
.TH I2CSET 8 "November 2008"
|
||||
.SH "NAME"
|
||||
i2cset \- set I2C registers
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B i2cset
|
||||
.RB [ -f ]
|
||||
.RB [ -y ]
|
||||
.RB [ "-m mask" ]
|
||||
.RB [ -r ]
|
||||
.I i2cbus
|
||||
.I chip-address
|
||||
.I data-address
|
||||
.RI [ value ]
|
||||
.RI ...
|
||||
.RI [ mode ]
|
||||
.br
|
||||
.B i2cset
|
||||
.B -V
|
||||
|
||||
.SH DESCRIPTION
|
||||
i2cset is a small helper program to set registers visible through the I2C
|
||||
bus.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B -V
|
||||
Display the version and exit.
|
||||
.TP
|
||||
.B -f
|
||||
Force access to the device even if it is already busy. By default, i2cset
|
||||
will refuse to access a device which is already under the control of a
|
||||
kernel driver. Using this flag is dangerous, it can seriously confuse the
|
||||
kernel driver in question. It can also cause i2cset to silently write to
|
||||
the wrong register. So use at your own risk and only if you know what
|
||||
you're doing.
|
||||
.TP
|
||||
.B -y
|
||||
Disable interactive mode. By default, i2cset will wait for a confirmation
|
||||
from the user before messing with the I2C bus. When this flag is used, it
|
||||
will perform the operation directly. This is mainly meant to be used in
|
||||
scripts.
|
||||
.TP
|
||||
.B -m mask
|
||||
The \fImask\fR parameter, if specified, describes which bits of \fIvalue\fR
|
||||
will be actually written to \fIdata-address\fR. Bits set to 1 in the mask
|
||||
are taken from \fIvalue\fR, while bits set to 0 will be read from
|
||||
\fIdata-address\fR and thus preserved by the operation. Please note that
|
||||
this parameter assumes that the read and write operations for the specified
|
||||
mode are symmetrical for the device you are accessing. This may or may not
|
||||
be the case, as neither I2C nor SMBus guarantees this.
|
||||
.TP
|
||||
.B -r
|
||||
Read back the value right after writing it, and compare the result with the
|
||||
value written. This used to be the default behavior. The same limitations
|
||||
apply as those of option \fB-m\fR.
|
||||
.PP
|
||||
There are three required options to i2cset. \fIi2cbus\fR indicates the number
|
||||
or name of the I2C bus to be scanned. This number should correspond to one of
|
||||
the busses listed by \fIi2cdetect -l\fR. \fIchip-address\fR specifies the
|
||||
address of the chip on that bus, and is an integer between 0x03 and 0x77.
|
||||
\fIdata-address\fR specifies the address on that chip to write to, and is an
|
||||
integer between 0x00 and 0xFF.
|
||||
.PP
|
||||
The \fIvalue\fR parameter, if specified, is the value to write to that
|
||||
location on the chip. If this parameter is omitted, then a short write is
|
||||
issued. For most chips, it simply sets an internal pointer to the target
|
||||
location, but doesn't actually write to that location. For a few chips
|
||||
though, in particular simple ones with a single register, this short write
|
||||
is an actual write. If the mode parameter is \fBs\fP or \fBi\fP, multiple
|
||||
values can be specified.
|
||||
.PP
|
||||
The \fImode\fR parameter, if specified, is one of the letters \fBb\fP,
|
||||
\fBw\fP, \fBs\fP, or \fBi\fP, corresponding to a write size of a single byte,
|
||||
a 16-bit word, a SMBus block write, or an I2C block write, respectively.
|
||||
For SMBus and I2C block writes, the write size is determined by the number
|
||||
of \fIvalue\fR parameters.
|
||||
Except for I2C block writes, a \fBp\fP can also be appended to the \fImode\fR
|
||||
parameter to enable PEC.
|
||||
If the \fImode\fR parameter is omitted, i2cset defaults to byte
|
||||
mode without PEC. The \fIvalue\fR provided must be within range for the
|
||||
specified data type (0x00-0xFF for byte and block writes, 0x0000-0xFFFF
|
||||
for words).
|
||||
Another possible mode is \fBc\fP, which doesn't write any value (so-called
|
||||
short write). You usually don't have to specify this mode, as it is the
|
||||
default when no value is provided, unless you also want to enable PEC.
|
||||
|
||||
.SH WARNING
|
||||
i2cset can be extremely dangerous if used improperly. It can confuse your
|
||||
I2C bus, cause data loss, or have more serious side effects. Writing to
|
||||
a serial EEPROM on a memory DIMM (chip addresses between 0x50 and 0x57) may
|
||||
DESTROY your memory, leaving your system unbootable! Be extremely careful
|
||||
using this program.
|
||||
|
||||
.SH SEE ALSO
|
||||
i2cdump(8), isaset(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Frodo Looijaard, Mark D. Studebaker and Jean Delvare
|
||||
|
||||
This manual page was originally written by David Z Maze <dmaze@debian.org> for
|
||||
the Debian GNU/Linux system.
|
||||
430
Script/i2c-tools-3.1.0/tools/i2cset.c
Normal file
430
Script/i2c-tools-3.1.0/tools/i2cset.c
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
/*
|
||||
i2cset.c - A user-space program to write an I2C register.
|
||||
Copyright (C) 2001-2003 Frodo Looijaard <frodol@dds.nl>, and
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2004-2010 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include "i2cbusses.h"
|
||||
#include "util.h"
|
||||
#include "../version.h"
|
||||
|
||||
static void help(void) __attribute__ ((noreturn));
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: i2cset [-f] [-y] [-m MASK] I2CBUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]\n"
|
||||
" I2CBUS is an integer or an I2C bus name\n"
|
||||
" ADDRESS is an integer (0x03 - 0x77)\n"
|
||||
" MODE is one of:\n"
|
||||
" c (byte, no value)\n"
|
||||
" b (byte data, default)\n"
|
||||
" w (word data)\n"
|
||||
" i (I2C block data)\n"
|
||||
" s (SMBus block data)\n"
|
||||
" Append p for SMBus PEC\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int check_funcs(int file, int size, int pec)
|
||||
{
|
||||
unsigned long funcs;
|
||||
|
||||
/* check adapter functionality */
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||
fprintf(stderr, "Error: Could not get the adapter "
|
||||
"functionality matrix: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus send byte");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus write byte");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus write word");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "SMBus block write");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
|
||||
fprintf(stderr, MISSING_FUNC_FMT, "I2C block write");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (pec
|
||||
&& !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C))) {
|
||||
fprintf(stderr, "Warning: Adapter does "
|
||||
"not seem to support PEC\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int confirm(const char *filename, int address, int size, int daddress,
|
||||
int value, int vmask, const unsigned char *block, int len,
|
||||
int pec)
|
||||
{
|
||||
int dont = 0;
|
||||
|
||||
fprintf(stderr, "WARNING! This program can confuse your I2C "
|
||||
"bus, cause data loss and worse!\n");
|
||||
|
||||
if (address >= 0x50 && address <= 0x57) {
|
||||
fprintf(stderr, "DANGEROUS! Writing to a serial "
|
||||
"EEPROM on a memory DIMM\nmay render your "
|
||||
"memory USELESS and make your system "
|
||||
"UNBOOTABLE!\n");
|
||||
dont++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "I will write to device file %s, chip address "
|
||||
"0x%02x, data address\n0x%02x, ", filename, address, daddress);
|
||||
if (size == I2C_SMBUS_BYTE)
|
||||
fprintf(stderr, "no data.\n");
|
||||
else if (size == I2C_SMBUS_BLOCK_DATA ||
|
||||
size == I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "data");
|
||||
for (i = 0; i < len; i++)
|
||||
fprintf(stderr, " 0x%02x", block[i]);
|
||||
fprintf(stderr, ", mode %s.\n", size == I2C_SMBUS_BLOCK_DATA
|
||||
? "smbus block" : "i2c block");
|
||||
} else
|
||||
fprintf(stderr, "data 0x%02x%s, mode %s.\n", value,
|
||||
vmask ? " (masked)" : "",
|
||||
size == I2C_SMBUS_BYTE_DATA ? "byte" : "word");
|
||||
if (pec)
|
||||
fprintf(stderr, "PEC checking enabled.\n");
|
||||
|
||||
fprintf(stderr, "Continue? [%s] ", dont ? "y/N" : "Y/n");
|
||||
fflush(stderr);
|
||||
if (!user_ack(!dont)) {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *end;
|
||||
const char *maskp = NULL;
|
||||
int res, i2cbus, address, size, file;
|
||||
int value, daddress, vmask = 0;
|
||||
char filename[20];
|
||||
int pec = 0;
|
||||
int flags = 0;
|
||||
int force = 0, yes = 0, version = 0, readback = 0;
|
||||
unsigned char block[I2C_SMBUS_BLOCK_MAX];
|
||||
int len;
|
||||
|
||||
/* handle (optional) flags first */
|
||||
while (1+flags < argc && argv[1+flags][0] == '-') {
|
||||
switch (argv[1+flags][1]) {
|
||||
case 'V': version = 1; break;
|
||||
case 'f': force = 1; break;
|
||||
case 'y': yes = 1; break;
|
||||
case 'm':
|
||||
if (2+flags < argc)
|
||||
maskp = argv[2+flags];
|
||||
flags++;
|
||||
break;
|
||||
case 'r': readback = 1; break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Unsupported option "
|
||||
"\"%s\"!\n", argv[1+flags]);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
|
||||
if (version) {
|
||||
fprintf(stderr, "i2cset version %s\n", VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc < flags + 4)
|
||||
help();
|
||||
|
||||
i2cbus = lookup_i2c_bus(argv[flags+1]);
|
||||
if (i2cbus < 0)
|
||||
help();
|
||||
|
||||
address = parse_i2c_address(argv[flags+2]);
|
||||
if (address < 0)
|
||||
help();
|
||||
|
||||
daddress = strtol(argv[flags+3], &end, 0);
|
||||
if (*end || daddress < 0 || daddress > 0xff) {
|
||||
fprintf(stderr, "Error: Data address invalid!\n");
|
||||
help();
|
||||
}
|
||||
|
||||
/* check for command/mode */
|
||||
if (argc == flags + 4) {
|
||||
/* Implicit "c" */
|
||||
size = I2C_SMBUS_BYTE;
|
||||
} else if (argc == flags + 5) {
|
||||
/* "c", "cp", or implicit "b" */
|
||||
if (!strcmp(argv[flags+4], "c")
|
||||
|| !strcmp(argv[flags+4], "cp")) {
|
||||
size = I2C_SMBUS_BYTE;
|
||||
pec = argv[flags+4][1] == 'p';
|
||||
} else {
|
||||
size = I2C_SMBUS_BYTE_DATA;
|
||||
}
|
||||
} else {
|
||||
/* All other commands */
|
||||
if (strlen(argv[argc-1]) > 2
|
||||
|| (strlen(argv[argc-1]) == 2 && argv[argc-1][1] != 'p')) {
|
||||
fprintf(stderr, "Error: Invalid mode '%s'!\n", argv[argc-1]);
|
||||
help();
|
||||
}
|
||||
switch (argv[argc-1][0]) {
|
||||
case 'b': size = I2C_SMBUS_BYTE_DATA; break;
|
||||
case 'w': size = I2C_SMBUS_WORD_DATA; break;
|
||||
case 's': size = I2C_SMBUS_BLOCK_DATA; break;
|
||||
case 'i': size = I2C_SMBUS_I2C_BLOCK_DATA; break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Invalid mode '%s'!\n", argv[argc-1]);
|
||||
help();
|
||||
}
|
||||
pec = argv[argc-1][1] == 'p';
|
||||
if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
if (pec && size == I2C_SMBUS_I2C_BLOCK_DATA) {
|
||||
fprintf(stderr, "Error: PEC not supported for I2C block writes!\n");
|
||||
help();
|
||||
}
|
||||
if (maskp) {
|
||||
fprintf(stderr, "Error: Mask not supported for block writes!\n");
|
||||
help();
|
||||
}
|
||||
if (argc > (int)sizeof(block) + flags + 5) {
|
||||
fprintf(stderr, "Error: Too many arguments!\n");
|
||||
help();
|
||||
}
|
||||
} else if (argc != flags + 6) {
|
||||
fprintf(stderr, "Error: Too many arguments!\n");
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
len = 0; /* Must always initialize len since it is passed to confirm() */
|
||||
|
||||
/* read values from command line */
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
value = strtol(argv[flags+4], &end, 0);
|
||||
if (*end || value < 0) {
|
||||
fprintf(stderr, "Error: Data value invalid!\n");
|
||||
help();
|
||||
}
|
||||
if ((size == I2C_SMBUS_BYTE_DATA && value > 0xff)
|
||||
|| (size == I2C_SMBUS_WORD_DATA && value > 0xffff)) {
|
||||
fprintf(stderr, "Error: Data value out of range!\n");
|
||||
help();
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
for (len = 0; len + flags + 5 < argc; len++) {
|
||||
value = strtol(argv[flags + len + 4], &end, 0);
|
||||
if (*end || value < 0) {
|
||||
fprintf(stderr, "Error: Data value invalid!\n");
|
||||
help();
|
||||
}
|
||||
if (value > 0xff) {
|
||||
fprintf(stderr, "Error: Data value out of range!\n");
|
||||
help();
|
||||
}
|
||||
block[len] = value;
|
||||
}
|
||||
value = -1;
|
||||
break;
|
||||
default:
|
||||
value = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (maskp) {
|
||||
vmask = strtol(maskp, &end, 0);
|
||||
if (*end || vmask == 0) {
|
||||
fprintf(stderr, "Error: Data value mask invalid!\n");
|
||||
help();
|
||||
}
|
||||
if (((size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA)
|
||||
&& vmask > 0xff) || vmask > 0xffff) {
|
||||
fprintf(stderr, "Error: Data value mask out of range!\n");
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
|
||||
if (file < 0
|
||||
|| check_funcs(file, size, pec)
|
||||
|| set_slave_addr(file, address, force))
|
||||
exit(1);
|
||||
|
||||
if (!yes && !confirm(filename, address, size, daddress,
|
||||
value, vmask, block, len, pec))
|
||||
exit(0);
|
||||
|
||||
if (vmask) {
|
||||
int oldvalue;
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
oldvalue = i2c_smbus_read_byte(file);
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
oldvalue = i2c_smbus_read_word_data(file, daddress);
|
||||
break;
|
||||
default:
|
||||
oldvalue = i2c_smbus_read_byte_data(file, daddress);
|
||||
}
|
||||
|
||||
if (oldvalue < 0) {
|
||||
fprintf(stderr, "Error: Failed to read old value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
value = (value & vmask) | (oldvalue & ~vmask);
|
||||
|
||||
if (!yes) {
|
||||
fprintf(stderr, "Old value 0x%0*x, write mask "
|
||||
"0x%0*x: Will write 0x%0*x to register "
|
||||
"0x%02x\n",
|
||||
size == I2C_SMBUS_WORD_DATA ? 4 : 2, oldvalue,
|
||||
size == I2C_SMBUS_WORD_DATA ? 4 : 2, vmask,
|
||||
size == I2C_SMBUS_WORD_DATA ? 4 : 2, value,
|
||||
daddress);
|
||||
|
||||
fprintf(stderr, "Continue? [Y/n] ");
|
||||
fflush(stderr);
|
||||
if (!user_ack(1)) {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pec && ioctl(file, I2C_PEC, 1) < 0) {
|
||||
fprintf(stderr, "Error: Could not set PEC: %s\n",
|
||||
strerror(errno));
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
res = i2c_smbus_write_byte(file, daddress);
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
res = i2c_smbus_write_word_data(file, daddress, value);
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
res = i2c_smbus_write_block_data(file, daddress, len, block);
|
||||
break;
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
res = i2c_smbus_write_i2c_block_data(file, daddress, len, block);
|
||||
break;
|
||||
default: /* I2C_SMBUS_BYTE_DATA */
|
||||
res = i2c_smbus_write_byte_data(file, daddress, value);
|
||||
break;
|
||||
}
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error: Write failed\n");
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pec) {
|
||||
if (ioctl(file, I2C_PEC, 0) < 0) {
|
||||
fprintf(stderr, "Error: Could not clear PEC: %s\n",
|
||||
strerror(errno));
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!readback) { /* We're done */
|
||||
close(file);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
res = i2c_smbus_read_byte(file);
|
||||
value = daddress;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
res = i2c_smbus_read_word_data(file, daddress);
|
||||
break;
|
||||
default: /* I2C_SMBUS_BYTE_DATA */
|
||||
res = i2c_smbus_read_byte_data(file, daddress);
|
||||
}
|
||||
close(file);
|
||||
|
||||
if (res < 0) {
|
||||
printf("Warning - readback failed\n");
|
||||
} else
|
||||
if (res != value) {
|
||||
printf("Warning - data mismatch - wrote "
|
||||
"0x%0*x, read back 0x%0*x\n",
|
||||
size == I2C_SMBUS_WORD_DATA ? 4 : 2, value,
|
||||
size == I2C_SMBUS_WORD_DATA ? 4 : 2, res);
|
||||
} else {
|
||||
printf("Value 0x%0*x written, readback matched\n",
|
||||
size == I2C_SMBUS_WORD_DATA ? 4 : 2, value);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
58
Script/i2c-tools-3.1.0/tools/util.c
Normal file
58
Script/i2c-tools-3.1.0/tools/util.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
util.c - helper functions
|
||||
Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "util.h"
|
||||
|
||||
/* Return 1 if we should continue, 0 if we should abort */
|
||||
int user_ack(int def)
|
||||
{
|
||||
char s[2];
|
||||
int ret;
|
||||
|
||||
if (!fgets(s, 2, stdin))
|
||||
return 0; /* Nack by default */
|
||||
|
||||
switch (s[0]) {
|
||||
case 'y':
|
||||
case 'Y':
|
||||
ret = 1;
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = def;
|
||||
}
|
||||
|
||||
/* Flush extra characters */
|
||||
while (s[0] != '\n') {
|
||||
int c = fgetc(stdin);
|
||||
if (c == EOF) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
s[0] = c;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
26
Script/i2c-tools-3.1.0/tools/util.h
Normal file
26
Script/i2c-tools-3.1.0/tools/util.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
util - helper functions
|
||||
Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H
|
||||
#define _UTIL_H
|
||||
|
||||
extern int user_ack(int def);
|
||||
|
||||
#endif /* _UTIL_H */
|
||||
1
Script/i2c-tools-3.1.0/version.h
Normal file
1
Script/i2c-tools-3.1.0/version.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define VERSION "3.1.0"
|
||||
Loading…
Add table
Add a link
Reference in a new issue