diff options
author | Mark D. Studebaker <mdsxyz123@yahoo.com> | 2001-04-03 02:39:23 +0000 |
---|---|---|
committer | Mark D. Studebaker <mdsxyz123@yahoo.com> | 2001-04-03 02:39:23 +0000 |
commit | 6c52f4b47f785dd870006e52fc788309575fb086 (patch) | |
tree | 08bd300abfea8af95f579200260f589abd43eeb5 | |
parent | a653703b6e283252cebfa9e23029b6e6e82a2b74 (diff) | |
download | lm-sensors-git-6c52f4b47f785dd870006e52fc788309575fb086.tar.gz |
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
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | doc/progs | 25 | ||||
-rw-r--r-- | prog/dump/Module.mk | 6 | ||||
-rw-r--r-- | prog/dump/i2cset.c | 232 |
4 files changed, 257 insertions, 9 deletions
@@ -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 @@ -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. diff --git a/prog/dump/Module.mk b/prog/dump/Module.mk index c306ed75..1a6df543 100644 --- a/prog/dump/Module.mk +++ b/prog/dump/Module.mk @@ -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. diff --git a/prog/dump/i2cset.c b/prog/dump/i2cset.c new file mode 100644 index 00000000..a66c0051 --- /dev/null +++ b/prog/dump/i2cset.c @@ -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); +} |