There's a bug in i2cset when using mask and a simple command (I2C_SMBUS_BYTE). I'm currently using this with a single byte 8-bit I/O expander device (PCF8574). but this is not device dependent. With and without a mask option, the byte to be written (argv[flags + 3]) is stored in "daddress" for later use. When argc == flags + 4, it's an implicit "c" and I2C_SMBUS_BYTE mode is set. In the case of I2C_SMBUS_BYTE, the write is perfomed with "i2c_smbus_write_byte(file, daddress)", which works fine as long as a mask was not set. If a mask is set (vmask), then the new value to write is constructed with the old value and the mask, and stored in "value" to be written back to the part, but this doesn't work for I2C_SMBUS_BYTE case, as it writes a single byte using "daddress" instead of "value" (which had the mask applied). The problem is that if the user is providing a mask and just the bits to be set or cleared according to the mask, then the only those bits will be set / cleared as the data on the command line, which is stored in daddress, and then written without any masking (e.g. the vmask routine to create "value"). The readback check succeeds because in the I2C_SMBUS_BYTE case, right after the read (to get "res"), it sets the vmask constructed "value" equal to the original "daddress" (which was just the bits to set without mask), and the "res" back from the device will be equal to that, never compared to the "value" that correctly constructed with the mask since it was just overwritten with the original "daddress" For now, I'm doing the reads / masks / writes via the calling script, as a workaround, but with 4.x in works, looks like a good opportunity to fix. Here is an example of the problem - note that I am trying to just set bit 4 on this device. You can see the bit pattern was properly constructed in the confirmation, but it goes off the rails when it talks about writing to a particular register (that's "daddress" in the printf). root@x:~# i2cset -r -m 0x10 2 0x21 0x10 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will write to device file /dev/i2c-2, chip address 0x21, data address 0x10, no data. Continue? [Y/n] y Old value 0xe1, write mask 0x10: Will write 0xf1 to register 0x10 Continue? [Y/n] y Value 0x10 written, readback matched root@x:~# i2cget 2 0x21 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will read from device file /dev/i2c-2, chip address 0x21, current data address, using read byte. Continue? [Y/n] y 0x10 root@x: