summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorgroeck <groeck@7894878c-1315-0410-8ee3-d5d059ff63e0>2011-01-29 17:15:01 +0000
committergroeck <groeck@7894878c-1315-0410-8ee3-d5d059ff63e0>2011-01-29 17:15:01 +0000
commit9c150edfb835afbfca300920dd30933864ea28ba (patch)
tree9bd3b1d53bfb071d8b1466857870efd1e6442fe5 /tools
parent98f62f07e4bb4acb4f5d471a03cdc7e2988ceb82 (diff)
downloadi2c-tools-9c150edfb835afbfca300920dd30933864ea28ba.tar.gz
Added support to write SMBus and I2C block commands to i2cset
git-svn-id: http://lm-sensors.org/svn/i2c-tools/trunk@5911 7894878c-1315-0410-8ee3-d5d059ff63e0
Diffstat (limited to 'tools')
-rw-r--r--tools/i2cset.821
-rw-r--r--tools/i2cset.c71
2 files changed, 81 insertions, 11 deletions
diff --git a/tools/i2cset.8 b/tools/i2cset.8
index 7e630c5..542954f 100644
--- a/tools/i2cset.8
+++ b/tools/i2cset.8
@@ -12,6 +12,7 @@ i2cset \- set I2C registers
.I chip-address
.I data-address
.RI [ value ]
+.RI ...
.RI [ mode ]
.br
.B i2cset
@@ -62,18 +63,24 @@ address of the chip on that bus, and is an integer between 0x03 and 0x77.
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 omited, then a short write is
+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.
+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 or
-\fBw\fP, corresponding to a write size of a single byte or a 16-bit word,
-respectively. 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
+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 bytes, 0x0000-0xFFFF for words).
+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.
diff --git a/tools/i2cset.c b/tools/i2cset.c
index 42319df..392262b 100644
--- a/tools/i2cset.c
+++ b/tools/i2cset.c
@@ -35,13 +35,15 @@ 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"
+ "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);
}
@@ -78,6 +80,19 @@ static int check_funcs(int file, int size, int pec)
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
@@ -90,7 +105,8 @@ static int check_funcs(int file, int size, int pec)
}
static int confirm(const char *filename, int address, int size, int daddress,
- int value, int vmask, int pec)
+ int value, int vmask, const unsigned char *block, int len,
+ int pec)
{
int dont = 0;
@@ -109,7 +125,16 @@ static int confirm(const char *filename, int address, int size, int daddress,
"0x%02x, data address\n0x%02x, ", filename, address, daddress);
if (size == I2C_SMBUS_BYTE)
fprintf(stderr, "no data.\n");
- else
+ 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");
@@ -136,6 +161,8 @@ int main(int argc, char *argv[])
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] == '-') {
@@ -180,6 +207,34 @@ int main(int argc, char *argv[])
help();
}
+ /* check for block data */
+ len = 0;
+ if (argc > flags + 5) {
+ switch (argv[argc-1][0]) {
+ case 's': size = I2C_SMBUS_BLOCK_DATA; break;
+ case 'i': size = I2C_SMBUS_I2C_BLOCK_DATA; break;
+ default:
+ size = 0;
+ break;
+ }
+ if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_I2C_BLOCK_DATA) {
+ pec = argv[argc-1][1] == 'p';
+ if (pec && size == I2C_SMBUS_I2C_BLOCK_DATA) {
+ fprintf(stderr, "Error: PEC not supported for I2C block writes!\n");
+ help();
+ }
+ for (len = 0; len < (int)sizeof(block) && len + flags + 5 < argc; len++) {
+ value = strtol(argv[flags + len + 4], &end, 0);
+ if (*end || value < 0 || value > 0xff) {
+ fprintf(stderr, "Error: Block data value invalid!\n");
+ help();
+ }
+ block[len] = value;
+ }
+ goto dofile;
+ }
+ }
+
if (argc > flags + 4) {
if (!strcmp(argv[flags+4], "c")
|| !strcmp(argv[flags+4], "cp")) {
@@ -236,6 +291,7 @@ int main(int argc, char *argv[])
help();
}
+dofile:
file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0);
if (file < 0
|| check_funcs(file, size, pec)
@@ -243,7 +299,7 @@ int main(int argc, char *argv[])
exit(1);
if (!yes && !confirm(filename, address, size, daddress,
- value, vmask, pec))
+ value, vmask, block, len, pec))
exit(0);
if (vmask) {
@@ -299,8 +355,15 @@ int main(int argc, char *argv[])
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");