add i2cset, simple utility to write a single location

in an i2c device, good for debugging.


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1057 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Mark D. Studebaker committed 2001-04-03 02:39:23 +00:00
1 parent a653703b6e
commit 6c52f4b47f
4 files changed
+257 -9

No files matched your search

+2 -1
View File
@@ -45,6 +45,7 @@ ask CVS about it:
Module w83781d: Don't reinitialize as99127f chip; this may cause fan/temp
reading changes
Programs i2cdetect, i2cdump: add devfs /dev/i2c/x support
Program i2cset: new
Program mkpatch.pl: Fix adm9240 typos, add more chips to Configure.help,
remove ltc1710
Program sens_update_rrd: new
@@ -222,7 +223,7 @@ ask CVS about it:
Modules: Much improved chip detection
Module maxilife: NEW
Module adm1021: MAX1617A now also supported
Module adm9024: DS1780 now also supported
Module adm9240: DS1780 now also supported
Module w83781d: W83782D and W83783S now also supported
Program sensors-detect: NEW
Library: All chips now supported
+19 -6
View File
@@ -2,6 +2,12 @@ This is a list of additional programs, that may or may not be installed by
`make install', and that usually can be found in the `prog' directory of
this package.
These programs are generally small utilities used for debugging,
and installation of the lm_sensors package, and for demonstrating
the use of the drivers and libraries in this package.
For more elaborate programs (for example, GUI sensor displays),
see useful_addresses.html.
* doc/developers/editticket (written in shell, not installed)
Calls netscape to edit a specific support ticket.
@@ -46,18 +52,23 @@ this package.
./doc-insmod.pl DRIVER
* prog/dump/i2cdump (written in C, not installed)
This program helps to dump the registers of a I2C device that understands
This program dumps the registers of a I2C device that understands
the 'byte data' or 'word data' and block read SMBus protocols.
Usual syntax:
./i2cdump 0 0x49 b
Here the '0' stands for the bus number (run i2cdump with no arguments
to list all installed busses).
0x49' is the device address, and 'b' or 'w' stands for byte
'0x49' is the device address, and 'b' or 'w' stands for byte
or word data.
* prog/dump/i2cset (written in C, not installed)
This program is used to write the register of a I2C device.
Usual syntax:
./i2cset bus device address data
* prog/dump/isadump (written in C, not installed)
This program helps to dump the registers of LM78-like chips, or more
exactly, chips which use an I/O-port for its address and one as its
This program dumps the registers of LM78-like chips, or more
exactly, chips which use one I/O-port for its address and one as its
data register. Usual syntax:
./isadump 0x295 0x296
@@ -85,7 +96,8 @@ this package.
* prog/rrd/sens_update_rrd (written in bash, not installed)
This script gathers sensors data and adds it to a round robin database
(RRD). RRD is then used to display the graphed data in web pages
(RRD). RRD is then used to display the graphed data in web pages.
See prog/rrd/README for more information.
* prog/sensord/sensord (written in C, installed by `make install-prog-sensord')
This daemon can be used to periodically log sensor readings from
@@ -100,7 +112,8 @@ this package.
file into account.
* prog/tellerstats/gather.sh, tellerstats.sh (written in bash, not installed)
These scripts gather sensors data and graph the data for web pages
These scripts gather sensors data and graph the data for web pages.
See prog/tellerstats/README for more information.
* prog/xeon/decode-xeon.pl (written in Perl, not installed)
ID ROM data decoding for Xeon processors.
+4 -2
View File
@@ -23,8 +23,10 @@ PROGDUMPDIR := $(MODULE_DIR)
# Regrettably, even 'simply expanded variables' will not put their currently
# defined value verbatim into the command-list of rules...
PROGDUMPTARGETS := $(MODULE_DIR)/isadump $(MODULE_DIR)/i2cdump
PROGDUMPSOURCES := $(MODULE_DIR)/isadump.c $(MODULE_DIR)/i2cdump.c
PROGDUMPTARGETS := $(MODULE_DIR)/isadump $(MODULE_DIR)/i2cdump \
$(MODULE_DIR)/i2cset
PROGDUMPSOURCES := $(MODULE_DIR)/isadump.c $(MODULE_DIR)/i2cdump.c \
$(MODULE_DIR)/i2cset.c
# Include all dependency files. We use '.rd' to indicate this will create
# executables.
+232
View File
@@ -0,0 +1,232 @@
/*
i2cset.c - A user-space program to dump I2C registers
Copyright (c) 2001 Frodo Looijaard <frodol@dds.nl>, and
Mark D. Studebaker <mdsxyz123@yahoo.com>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
void help(void)
{
FILE *fptr;
char s[100];
fprintf(stderr,"Syntax: i2cset I2CBUS CHIP-ADDRESS DATA-ADDRESS VALUE [MODE]\n");
fprintf(stderr," MODE is 'b[yte]' or 'w[ord]' (default b)\n");
fprintf(stderr," I2CBUS is an integer\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);
}
exit(1);
}
int main(int argc, char *argv[])
{
char *end;
int res,i2cbus,address,size,file;
int value, daddress;
int e1, e2, e3;
char filename1[20];
char filename2[20];
char filename3[20];
char *filename;
long funcs;
if (argc < 5)
help();
i2cbus = strtol(argv[1],&end,0);
if (*end || (i2cbus < 0) || (i2cbus > 0x3f)) {
fprintf(stderr,"Error: I2CBUS argument invalid!\n");
help();
}
address = strtol(argv[2],&end,0);
if (*end || (address < 0) || (address > 0x7f)) {
fprintf(stderr,"Error: Chip address invalid!\n");
help();
}
daddress = strtol(argv[3],&end,0);
if (*end || (daddress < 0) || (daddress > 0xff)) {
fprintf(stderr,"Error: Data address invalid!\n");
help();
}
value = strtol(argv[4],&end,0);
if (*end) {
fprintf(stderr,"Error: Data value invalid!\n");
help();
}
if (argc < 6) {
fprintf(stderr,"Warning: no size specified (using byte-data access)\n");
size = I2C_SMBUS_BYTE_DATA;
} else if (!strcmp(argv[5],"b"))
size = I2C_SMBUS_BYTE_DATA;
else if (!strcmp(argv[5],"w"))
size = I2C_SMBUS_WORD_DATA;
else {
fprintf(stderr,"Error: Invalid mode!\n");
help();
}
if ((value < 0) || ((size == I2C_SMBUS_BYTE_DATA) && (value > 0xff))
|| ((size == I2C_SMBUS_WORD_DATA) && (value > 0x0ffff))) {
fprintf(stderr,"Error: Data value out of range!\n");
help();
}
/*
* Try all three variants and give the correct error message
* upon failure
*/
sprintf(filename1,"/dev/i2c-%d",i2cbus);
sprintf(filename2,"/dev/i2c%d",i2cbus);
sprintf(filename3,"/dev/i2c/%d",i2cbus);
if ((file = open(filename1,O_RDWR)) < 0) {
e1 = errno;
if ((file = open(filename2,O_RDWR)) < 0) {
e2 = errno;
if ((file = open(filename3,O_RDWR)) < 0) {
e3 = errno;
if(e1 == ENOENT && e2 == ENOENT && e3 == ENOENT) {
fprintf(stderr,"Error: Could not open file `%s', `%s', or `%s': %s\n",
filename1,filename2,filename3,strerror(ENOENT));
}
if (e1 != ENOENT) {
fprintf(stderr,"Error: Could not open file `%s' : %s\n",
filename1,strerror(e1));
if(e1 == EACCES)
fprintf(stderr,"Run as root?\n");
}
if (e2 != ENOENT) {
fprintf(stderr,"Error: Could not open file `%s' : %s\n",
filename2,strerror(e2));
if(e2 == EACCES)
fprintf(stderr,"Run as root?\n");
}
if (e3 != ENOENT) {
fprintf(stderr,"Error: Could not open file `%s' : %s\n",
filename3,strerror(e3));
if(e3 == EACCES)
fprintf(stderr,"Run as root?\n");
}
exit(1);
} else {
filename = filename3;
}
} else {
filename = filename2;
}
} else {
filename = filename1;
}
/* check adapter functionality */
if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
fprintf(stderr,
"Error: Could not get the adapter functionality matrix: %s\n",
strerror(errno));
exit(1);
}
switch(size) {
case I2C_SMBUS_BYTE_DATA:
if (! (funcs &
(I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_READ_BYTE_DATA))) {
fprintf(stderr, "Error: Adapter for i2c bus %d", i2cbus);
fprintf(stderr, " does not have byte write capability\n");
exit(1);
}
break;
case I2C_SMBUS_WORD_DATA:
if (! (funcs &
(I2C_FUNC_SMBUS_WRITE_WORD_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA))) {
fprintf(stderr, "Error: Adapter for i2c bus %d", i2cbus);
fprintf(stderr, " does not have word write capability\n");
exit(1);
}
break;
}
/* use FORCE so that we can write registers even when
a driver is also running */
if (ioctl(file,I2C_SLAVE_FORCE,address) < 0) {
fprintf(stderr,"Error: Could not set address to %d: %s\n",address,
strerror(errno));
exit(1);
}
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\n");
fprintf(stderr, "may render your memory USELESS and make your system UNBOOTABLE!!!\n");
fprintf(stderr, "Are you SURE that you want to write to the chip at address 0x%.2x? (n) ", address);
res = getchar();
if(res != 'y' && res != 'Y')
exit(1);
}
fprintf(stderr," I will write device file %s, chip address 0x%.2x, data address 0x%.2x, data 0x%x, mode %s\n",
filename, address, daddress, value,
size == I2C_SMBUS_BYTE_DATA ? "byte" : "word");
fprintf(stderr," You have five seconds to reconsider and press CTRL-C!\n\n");
sleep(5);
e1 = 0;
if (size == I2C_SMBUS_WORD_DATA) {
res = i2c_smbus_write_word_data(file, daddress, value);
} else {
res = i2c_smbus_write_byte_data(file, daddress, value);
}
if(res < 0) {
fprintf(stderr, "Warning - write failed\n");
e1++;
}
if (size == I2C_SMBUS_WORD_DATA) {
res = i2c_smbus_read_word_data(file, daddress);
} else {
res = i2c_smbus_read_byte_data(file, daddress);
}
if(res < 0) {
fprintf(stderr, "Warning - readback failed\n");
e1++;
} else {
if(res != value) {
e1++;
if (size == I2C_SMBUS_WORD_DATA)
fprintf(stderr, "Warning - data mismatch - wrote 0x%.4x, read back 0x%.4x\n", value, res);
else
fprintf(stderr, "Warning - data mismatch - wrote 0x%.2x, read back 0x%.2x\n", value, res);
} else {
fprintf(stderr, "Value 0x%x written, readback matched\n", value);
}
}
exit(e1);
}