Search code examples
linux-device-driverraspberry-pi3i2c

Variable sized i2c reads Raspberry


I am trying to interface A71CH with raspberry PI 3 over i2c, the device requires repeated starts and when a read request is made the first byte the device sends, is always the length of the whole message. When I am trying to make a read, instead of reading a fixed sized message , I want to read the first byte then send NACK signal to the slave after certain amount of bytes have been received that is indicated with the first byte. I used to following code but could not get the results I expected because it only read one byte than sends a NACK signal as you can see below.

struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2];
int r = 0;
int i = 0;

if (bus != I2C_BUS_0) // change if bus 0 is not the correct bus
{
    printf("axI2CWriteRead on wrong bus %x (addr %x)\n", bus, addr);
}

messages[0].addr  = axSmDevice_addr;
messages[0].flags = 0;
messages[0].len   = txLen;
messages[0].buf   = pTx;

// NOTE:
// By setting the 'I2C_M_RECV_LEN' bit in 'messages[1].flags' one ensures
// the I2C Block Read feature is used.
messages[1].addr  = axSmDevice_addr;
messages[1].flags = I2C_M_RD | I2C_M_RECV_LEN|I2C_M_IGNORE_NAK;
messages[1].len   = 256;
messages[1].buf   = pRx;
messages[1].buf[0] = 1;

// NOTE:
// By passing the two message structures via the packets structure as
// a parameter to the ioctl call one ensures a Repeated Start is triggered.
packets.msgs      = messages;
packets.nmsgs     = 2;

// Send the request to the kernel and get the result back
r = ioctl(axSmDevice, I2C_RDWR, &packets);

Signals

Is there any way that allows me to make variable sized i2c reads ? What can I do to make it work ? Thanks for looking.


Solution

  • Raspbery doesn't support SMBUS Block Reads, only way to overcome this is to do bitbanging on GPIO pins. As @Ian Abbott mentioned above, I managed to modify bbI2CZip function to fit my need by checking the first byte of the received message and updating the read length afterwards.