Add support to write SMBus and I2C block data to i2cset. Rev 2: Included review feedback -- Index: tools/i2cset.8 =================================================================== --- tools/i2cset.8 (revision 5909) +++ tools/i2cset.8 (working copy) @@ -12,6 +12,7 @@ .I chip-address .I data-address .RI [ value ] +.RI ... .RI [ mode ] .br .B i2cset @@ -62,18 +63,24 @@ 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. Index: tools/i2cset.c =================================================================== --- tools/i2cset.c (revision 5909) +++ tools/i2cset.c (working copy) @@ -35,13 +35,15 @@ 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 @@ return -1; } break; + + case I2C_SMBUS_BLOCK_DATA: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) { + fprintf(stderr, MISSING_FUNC_FMT, "SMBus block read"); + return -1; + } + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { + fprintf(stderr, MISSING_FUNC_FMT, "I2C block read"); + return -1; + } + break; } if (pec @@ -90,7 +105,8 @@ } 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 @@ "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 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 @@ 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 @@ help(); } +dofile: file = open_i2c_dev(i2cbus, filename, sizeof(filename), 0); if (file < 0 || check_funcs(file, size, pec) @@ -243,7 +299,7 @@ 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 @@ 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"); Index: CHANGES =================================================================== --- CHANGES (revision 5909) +++ CHANGES (working copy) @@ -3,6 +3,7 @@ SVN i2c-dev.h: Make value arrays const for block write functions + i2cset: Add support for SMBus and I2C block writes 3.0.3 (2010-12-12) Makefile: Let the environment set CC and CFLAGS -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html