| diff -aruN i2c-tools-3.1.2/tools/i2cgetwide.8 i2c-tools-3.1.2.N/tools/i2cgetwide.8 |
| --- i2c-tools-3.1.2/tools/i2cgetwide.8 1969-12-31 16:00:00.000000000 -0800 |
| +++ i2c-tools-3.1.2.N/tools/i2cgetwide.8 2016-03-21 14:39:29.584650609 -0700 |
| @@ -0,0 +1,68 @@ |
| +.TH I2CGETWIDE 8 "March 2016" |
| +.SH "NAME" |
| +i2cgetwide \- read from I2C chip registers of arbitrary data/address length |
| + |
| +.SH SYNOPSIS |
| +.B i2cgetwide |
| +.RB [ -f ] |
| +.RB [ -y ] |
| +.I i2cbus |
| +.I chip-address |
| +.I data-address-length |
| +.I data-address |
| +.I data-length |
| +.br |
| +.B i2cgetwide |
| +.B -V |
| + |
| +.SH DESCRIPTION |
| +i2cgetwide is a small helper program to read registers visible through the I2C |
| +bus. This should be used for registers whose addresses are greater than 1 byte |
| +and register value is greater than 1 byte. |
| + |
| +.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, i2cgetwide |
| +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 i2cgetwide 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, i2cgetwide 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 five required options to i2cgetwide. \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-length\fR specifies the length of the address of the register |
| +on that chip. |
| +.PP |
| +\fIdata-length\fR specifies the length of the value of the register |
| +on that chip. |
| +.PP |
| +\fIdata-address\fR specifies the address on that chip to read from, and it is a |
| +list of length \fIdata-address-length\fR. |
| + |
| +.SH WARNING |
| +i2cgetwide 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) i2cget(8) |
| + |
| +.SH AUTHOR |
| +Renga Aravamudhan |
| + |
| +This manual page was strongly inspired from those written by Jean Delvare |
| +for i2cget. |
| diff -aruN i2c-tools-3.1.2/tools/i2cgetwide.c i2c-tools-3.1.2.N/tools/i2cgetwide.c |
| --- i2c-tools-3.1.2/tools/i2cgetwide.c 1969-12-31 16:00:00.000000000 -0800 |
| +++ i2c-tools-3.1.2.N/tools/i2cgetwide.c 2016-03-22 16:35:55.809045663 -0700 |
| @@ -0,0 +1,192 @@ |
| +/* |
| + i2cgetwide.c - A user-space program to read a wide I2C register. |
| + |
| + Based on i2cget.c: |
| + Copyright (C) 2001-2003 Frodo Looijaard <frodol@dds.nl>, and |
| + Mark D. Studebaker <mdsxyz123@yahoo.com> |
| + Copyright (C) 2004-2005 Jean Delvare |
| + Copyright (C) 2005-2012 Jean Delvare <jdelvare@suse.de> |
| + |
| + 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 <sys/ioctl.h> |
| +#include <errno.h> |
| +#include <stdint.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: i2cgetwide [-f] [-y] [-V] I2CBUS CHIP-ADDRESS DATA-ADDRESS-LENGTH DATA-LENGTH DATA_ADDRESS\n" |
| + " I2CBUS is an integer or an I2C bus name\n" |
| + " CHIP-ADDRESS is an integer (0x03 - 0x77)\n" |
| + " DATA-ADDRESS-LENGTH is the length of register address in bytes\n" |
| + " DATA-LENGTH is the length of the register content in bytes\n" |
| + " DATA-ADDRESS is the register address is specified as a list of DATA-ADDRESS-LENGTH bytes\n"); |
| + exit(1); |
| +} |
| + |
| +static int confirm(const char *filename, int address) |
| +{ |
| + int dont = 0; |
| + |
| + fprintf(stderr, "WARNING! This program can confuse your I2C " |
| + "bus, cause data loss and worse!\n"); |
| + |
| + fprintf(stderr, "I will read from device file %s, chip " |
| + "address 0x%02x, ", filename, address); |
| + |
| + fprintf(stderr, "Continue? [Y/n] "); |
| + fflush(stderr); |
| + if (!user_ack(!dont)) { |
| + fprintf(stderr, "Aborting on user request.\n"); |
| + return 0; |
| + } |
| + |
| + return 1; |
| +} |
| + |
| +static __s32 i2c_rdwr_read(int file, __u16 address, |
| + void *reg, size_t reg_size, |
| + void *buf, size_t count) |
| +{ |
| + struct i2c_rdwr_ioctl_data args; |
| + struct i2c_msg xfer[2]; |
| + |
| + xfer[0].addr = address; |
| + xfer[0].flags = 0; |
| + xfer[0].buf = reg; |
| + xfer[0].len = reg_size; |
| + |
| + xfer[1].addr = address; |
| + xfer[1].flags = I2C_M_RD; |
| + xfer[1].buf = buf; |
| + xfer[1].len = count; |
| + |
| + args.msgs = xfer; |
| + args.nmsgs = 2; |
| + |
| + return ioctl(file,I2C_RDWR,&args); |
| +} |
| + |
| +int main(int argc, char *argv[]) |
| +{ |
| + int res, i2cbus, address, file; |
| + int daddress_length, data_length, i; |
| + char *end; |
| + unsigned char daddress[I2C_SMBUS_I2C_BLOCK_MAX], data[I2C_SMBUS_I2C_BLOCK_MAX]; |
| + char filename[20]; |
| + 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, "i2cgetwide version %s\n", VERSION); |
| + exit(0); |
| + } |
| + |
| + if (argc < flags + 5) |
| + help(); |
| + |
| + i2cbus = lookup_i2c_bus(argv[flags+1]); |
| + if (i2cbus < 0) |
| + help(); |
| + |
| + address = parse_i2c_address(argv[flags+2]); |
| + if (address < 0) |
| + help(); |
| + |
| + daddress_length = strtol(argv[flags+3], &end, 0); |
| + if (*end) { |
| + fprintf(stderr, "Error in register address length\n"); |
| + help(); |
| + } |
| + if ( (daddress_length <= 0) || (daddress_length > 4) ) { |
| + fprintf(stderr, "Register address length cannot be <=0 or >4 \n"); |
| + help(); |
| + } |
| + |
| + data_length = strtol(argv[flags+4], &end, 0); |
| + if (*end) { |
| + fprintf(stderr, "Error in data length\n"); |
| + help(); |
| + } |
| + if ( (data_length <= 0) || (data_length > 4) ) { |
| + fprintf(stderr, "Register data length cannot be <=0 or >4 \n"); |
| + help(); |
| + } |
| + |
| + if (argc < flags + 5 + daddress_length) { |
| + fprintf(stderr, "Error in register address \n"); |
| + help(); |
| + } |
| + |
| + for(i = 0; i < daddress_length; i++) { |
| + daddress[i] = strtol(argv[flags+5+i], &end, 0); |
| + if (*end) { |
| + fprintf(stderr, "Error in register address\n"); |
| + help(); |
| + } |
| + } |
| + |
| + file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0); |
| + if (file < 0 |
| + || set_slave_addr(file, address, force)) |
| + exit(1); |
| + |
| + if (!yes && !confirm(filename, address)) |
| + exit(0); |
| + |
| + res = i2c_rdwr_read(file, address, daddress, daddress_length, |
| + data, data_length); |
| + close(file); |
| + |
| + if (res < 0) { |
| + fprintf(stderr, "Error: Read failed\n"); |
| + exit(2); |
| + } |
| + |
| + printf("0x"); |
| + for(i = 0; i < data_length; i++) |
| + printf("%02x", data[i]); |
| + printf("\n"); |
| + |
| + exit(0); |
| +} |
| diff -aruN i2c-tools-3.1.2/tools/Module.mk i2c-tools-3.1.2.N/tools/Module.mk |
| --- i2c-tools-3.1.2/tools/Module.mk 2014-02-20 00:37:15.711233000 -0800 |
| +++ i2c-tools-3.1.2.N/tools/Module.mk 2016-03-21 14:39:29.584650609 -0700 |
| @@ -13,7 +13,7 @@ |
| -Wcast-align -Wwrite-strings -Wnested-externs -Winline \ |
| -W -Wundef -Wmissing-prototypes -Iinclude |
| |
| -TOOLS_TARGETS := i2cdetect i2cdump i2cset i2cget |
| +TOOLS_TARGETS := i2cdetect i2cdump i2cset i2cget i2cgetwide |
| |
| # |
| # Programs |
| @@ -31,6 +31,9 @@ |
| $(TOOLS_DIR)/i2cget: $(TOOLS_DIR)/i2cget.o $(TOOLS_DIR)/i2cbusses.o $(TOOLS_DIR)/util.o |
| $(CC) $(LDFLAGS) -o $@ $^ |
| |
| +$(TOOLS_DIR)/i2cgetwide: $(TOOLS_DIR)/i2cgetwide.o $(TOOLS_DIR)/i2cbusses.o $(TOOLS_DIR)/util.o |
| + $(CC) $(LDFLAGS) -o $@ $^ |
| + |
| # |
| # Objects |
| # |
| @@ -47,6 +50,9 @@ |
| $(TOOLS_DIR)/i2cget.o: $(TOOLS_DIR)/i2cget.c $(TOOLS_DIR)/i2cbusses.h $(TOOLS_DIR)/util.h version.h $(INCLUDE_DIR)/linux/i2c-dev.h |
| $(CC) $(CFLAGS) $(TOOLS_CFLAGS) -c $< -o $@ |
| |
| +$(TOOLS_DIR)/i2cgetwide.o: $(TOOLS_DIR)/i2cgetwide.c $(TOOLS_DIR)/i2cbusses.h $(TOOLS_DIR)/util.h version.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 $@ |
| |