6

I'm trying to configure a SAA6752HS chip (a MPEG-2 encoder) through I2C bus using a Raspberry Pi as a development kit. It was a piece of cake until I had to write at the address 0xC2 of the chip. For this task, I have to use an I2C command that expects a payload of size 189 bytes. So then I stumbled upon a 32 bytes limitation inside the I2C driver, defined by I2C_SMBUS_BLOCK_MAX, in /usr/include/linux/i2c.h. It is not possible to force different values of max limit. Everything around I2C lib end up into the function i2c_smbus_access and any request with more then 32 bytes makes ioctl returns -1. I have no idea how to debug it so far.

static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
                                     int size, union i2c_smbus_data *data)
{
        struct i2c_smbus_ioctl_data args;

        args.read_write = read_write;
        args.command = command;
        args.size = size;
        args.data = data;
        return ioctl(file,I2C_SMBUS,&args);
}

I can't understand why there is such limitation, considering that there are devices that require more than 32 bytes of payload data to work (SAA6752HS is such an example).

Are there a way to overcome such limitation without rewrite a new driver?

Thank you in advance.

marcelo.guedes
  • 482
  • 5
  • 12
  • I2C_SMBUS_BLOCK_MAX has this comment: `/* As specified in SMBus standard */` Are you sure the SAA6752HS speaks SMBus and not I2C ? SMBus and I2C are compatible in many ways, but they're not the same thing. – nos Sep 22 '14 at 20:54
  • Yes @nos, I read it a lot around the internet but it is far away from a solution. It only confirms the problem. So what is the deal with SAA6752HS? And other chips with the same issue? So there is no way to talk with a non SMBus standard I2C chip using the default I2C linux driver? Why is the I2C driver limited to only SMBus? – marcelo.guedes Sep 22 '14 at 20:56
  • @nos I am sure that SAA6752HS is NOT SMBus standard, but I couldn't figure out how to deal with a non SMBus I2C interface using the I2C Linux driver. How can I deal with it? – marcelo.guedes Sep 22 '14 at 20:59
  • +3000 I have wasted a lot of time on the same problem for another chip – gregoiregentil Jul 10 '15 at 04:47

2 Answers2

9

Here's the documentation for the Linux i2c interface: https://www.kernel.org/doc/Documentation/i2c/dev-interface

At the simplest level you can use ioctl(I2C_SLAVE) to set the slave address and the write system call to write the command. Something like:

i2c_write(int file, int address, int subaddress, int size, char *data) {
    char buf[size + 1];               // note: variable length array
    ioctl(file, I2C_SLAVE, address);  // real code would need to check for an error
    buf[0] = subaddress;              // need to send everything in one call to write
    memcpy(buf + 1, data, size);      // so copy subaddress and data to a buffer 
    write(file, buf, size + 1); 
}
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
  • 1
    Thank you. It worked. The direct reference to I2C_SLAVE was the missing piece for me. I really don't get why this subject has so much misinformation around the Internet. You can find a lot of forum threads without a simple answer like that. I hope this post can help others. – marcelo.guedes Sep 23 '14 at 11:31
  • +3000 I have wasted a lot of time on the same problem for another chip – gregoiregentil Jul 10 '15 at 04:47
  • I have to say that on my device that is using I2C_SLAVE the limit is 60 bytes. – Owl Sep 26 '18 at 13:11
  • Do you know who is responsible for the driver? The kernel doc does not say. I feel a bug report should be submitted for this issue. – jww Dec 27 '19 at 01:30
  • @jww, perhaps you may read this first: https://lore.kernel.org/linux-input/20191021163956.GB1353@jack.zhora.eu/T/ – 0andriy Jan 03 '20 at 11:04
  • What is `I2C_SLAVE`? I see you are specifying the slave address with `address` but what is `I2C_SLAVE` defined as? – Code Doggo Sep 22 '20 at 20:01
  • @CodeDoggo It would be defined in one of the two header files you need to include, either `` or ``, See the linked documentation in my answer above. – Ross Ridge Sep 22 '20 at 20:16
  • write command is returning -1 , not sure if we can use direct write. – Alok Prasad Nov 03 '22 at 14:38
-2

if write command is returning -1 make use open fd using int fd = open("/dev/i2c-1", O_RDWR) not int fd = open("/dev/i2c-1", I2C_RDWR)

Alok Prasad
  • 622
  • 7
  • 12