I2c tool reads sensor error

Hey, I am debugging the IMX258 sensor, I want to implement dynamic debugging 16bit registers, but I can’t use i2cget, i2cset, i2cdump. I wrote an application to read the write, but the read and write sensors have been abnormal:
“[ 114.047928] tegra-vii2c 546c0000.i2c: no acknowledge from address 0x1a
ioctl error2: Remote I/O error”

code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#if 0
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

#else
#define I2C_M_WT 0x0000/* write data, from master to slave /
#define I2C_M_RD 0x0001/
read data, from slave to master /
#define I2C_M_TEN 0x0010 /
this is a ten bit chip address /
#define I2C_M_STOP 0x8000 /
if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_NOSTART 0x4000 /
if I2C_FUNC_NOSTART /
#define I2C_M_REV_DIR_ADDR 0x2000 /
if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_IGNORE_NAK 0x1000 /
if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_NO_RD_ACK 0x0800 /
if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_RECV_LEN 0x0400 /
length will be first received byte */

#define I2C_ADDR (0x48>>1)

#define I2C_ADDR_16BIT 1 // 1:16bit i2c_addr 0:8bit i2c_addr

#define I2C_RETRIES 0x0701 /*设置收不到ACK时的重试次数 /
#define I2C_TIMEOUT 0x0702 /
设置超时时限的jiffies */
#define I2C_SLAVE 0x0703 /*设置从机地址 /
#define I2C_SLAVE_FORCE 0x0706 /
强制设置从机地址 */
#define I2C_TENBIT 0x0010 //0x0704 /*选择地址位长:=0 for 7bit , != 0 for 10 bit */
#define I2C_FUNCS 0x0705 /*获取适配器支持的功能 */
#define I2C_RDWR 0x0707 /*Combined R/W transfer (one STOP only) /
#define I2C_PEC 0x0708 /
!= 0 to use PEC with SMBus */
#define I2C_SMBUS 0x0720 /*SMBus transfer */
#define I2C_SMBUS_BYTE_DATA 2
#define I2C_SMBUS_READ 1
#define I2C_SMBUS_WRITE 0
#define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 8
#define I2C_SLAVE_FORCE 0x0706
#define I2C_SMBUS_BLOCK_MAX 32

// exact-width types
typedef chars8;
typedef shorts16;
typedef ints32;
typedef unsigned charu8;
typedef unsigned shortu16;
typedef unsigned intu32;
typedef floatf32;
typedef doublef64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;

union i2c_smbus_data {
unsigned char byte;
unsigned short word;
unsigned char block[I2C_SMBUS_BLOCK_MAX + 2];
};

struct i2c_smbus_ioctl_data {
char read_write;
unsigned char command;
int size;
union i2c_smbus_data *data;
};

struct i2c_msg {
u16 addr;/* slave address*/
u16 flags;
u16 len;/* msg length*/
u8 buf;/ pointer to msg data*/
} ;

/* In ./include/linux/i2c-dev.h /
struct i2c_rdwr_ioctl_data {
/
pointers to i2c_msgs */
struct i2c_msg msgs;
/
number of i2c_msgs */
u32 nmsgs;
};

#endif

int Standard_i2c_open(int index)
{
char dev_name[32];

sprintf(dev_name, "/dev/i2c-%d", index);
printf("%s:index = %d\r\n",dev_name,index);

return open("/dev/i2c-6", O_RDWR);

}

#if I2C_ADDR_16BIT
int write_16bit_i2c(int bus_index, u8 device_addr/8bits/, u32 register_addr, unsigned char *pBuffer)
{
struct i2c_rdwr_ioctl_data e2prom_data;
int i2c_dev_fd = -1;
char reg_buf[3]={0,0,0};
int ret;
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf(“standard_i2c_read Standard_i2c_open Failed\n”);
goto OVER;
}

ioctl(i2c_dev_fd,I2C_TIMEOUT,1);/*超时时间*/
ioctl(i2c_dev_fd,I2C_RETRIES,2);/*重复次数*/

e2prom_data.nmsgs=1; 
e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));
if(!e2prom_data.msgs)
{
    perror("malloc error");
    goto _OVER_;
}

reg_buf[0] = (register_addr >> 8) & 0xFF; //e2prom数据地址 16bit
reg_buf[1] = register_addr & 0xFF ; //e2prom数据地址
reg_buf[2] = pBuffer[0] ; //写一个数据

(e2prom_data.msgs[0]).len=3; //
(e2prom_data.msgs[0]).addr=device_addr; // e2prom 设备地址
(e2prom_data.msgs[0]).flags=I2C_M_WT; //write
(e2prom_data.msgs[0]).buf = reg_buf;

ret=ioctl(i2c_dev_fd,I2C_RDWR,(unsigned long)&e2prom_data);
if(ret<0)
{
    perror("ioctl error2");
    goto _OVER_;
}
printf("** %x ** \n",pBuffer[0]);


_OVER_:
if(i2c_dev_fd >= 0)
{
    close(i2c_dev_fd);
}
if(e2prom_data.msgs != NULL)
{
    free(e2prom_data.msgs);
}

}

int read_16bit_i2c(int bus_index, u8 device_addr/8bits/, u32 register_addr, unsigned char *pBuffer)
{
struct i2c_rdwr_ioctl_data e2prom_data;
int i2c_dev_fd = -1;
char reg_buf[2]={0,0},buf[2]={0,0};
int ret;
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf(“standard_i2c_read Standard_i2c_open Failed\n”);
goto OVER;
}
printf(“%s:%d\r\n”,FUNCTION,LINE);
ioctl(i2c_dev_fd,I2C_TIMEOUT,5);/超时时间/
ioctl(i2c_dev_fd,I2C_RETRIES,2);/重复次数/
printf(“%s:%d\r\n”,FUNCTION,LINE);

e2prom_data.nmsgs=2; 
e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));
if(!e2prom_data.msgs)
{
    perror("malloc error");
    goto _OVER_;
}

reg_buf[0] = (register_addr >> 8) & 0xFF; //e2prom数据地址 16bit
reg_buf[1] = register_addr & 0xFF ; //e2prom数据地址

e2prom_data.nmsgs=2;
(e2prom_data.msgs[0]).len=2; //e2prom 要写的字节数
(e2prom_data.msgs[0]).addr=device_addr; // e2prom 设备地址
(e2prom_data.msgs[0]).flags=I2C_M_WT; //write
(e2prom_data.msgs[0]).buf = reg_buf;

(e2prom_data.msgs[1]).len=1; //读出的数据个数
(e2prom_data.msgs[1]).addr=device_addr; // e2prom 设备地址
(e2prom_data.msgs[1]).flags=I2C_M_RD;//read
(e2prom_data.msgs[1]).buf=buf;

ret=ioctl(i2c_dev_fd,I2C_RDWR,(unsigned long)&e2prom_data);
if(ret<0)
{
    perror("ioctl error2");
    goto _OVER_;
}
printf("***0x%x***\n",(e2prom_data.msgs[1]).buf[0]);
 
pBuffer[0] = (e2prom_data.msgs[1]).buf[0];

_OVER_:
if(i2c_dev_fd >= 0)
{
    close(i2c_dev_fd);
}
if(e2prom_data.msgs != NULL)
{
    free(e2prom_data.msgs);
}

}

//#else

int read_8bit_i2c(int bus_index, unsigned char device_addr/8bits/, unsigned char register_addr, unsigned char *pBuffer, int byte_number)
{
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data smbus_data;
int ret_val = -1;
int i2c_dev_fd = -1;
int index = 0;

/**/
if(byte_number >= I2C_SMBUS_BLOCK_MAX)
{
    printf("standard_i2c_read Invalid parameter(%d >= %d)\n", byte_number, I2C_SMBUS_BLOCK_MAX);
    return -1;
}

/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
    printf("standard_i2c_read Standard_i2c_open Failed\n");
    goto _OVER_;
}

/*set address*/
ioctl(i2c_dev_fd, I2C_TENBIT, 0);
if(ioctl(i2c_dev_fd, I2C_SLAVE_FORCE, (device_addr)& 0x7f) < 0)
{
    perror("i2c ioctl:");
    printf("standard_i2c_read ioctl(I2C_SLAVE) Failed\n");
    goto _OVER_;
}

/**/
smbus_data.block[0] = byte_number;

ioctl_data.read_write = I2C_SMBUS_READ;
ioctl_data.command = register_addr;
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
ioctl_data.data = &smbus_data;
if(ioctl(i2c_dev_fd, I2C_SMBUS, &ioctl_data) != 0)
{
    printf("standard_i2c_read ioctl(I2C_SMBUS) Failed(%d)\n", index);
    goto _OVER_;
}

if(smbus_data.block[0] != byte_number)
{
    printf("standard_i2c_read ioctl read Failed(%d)(%d)\n", smbus_data.block[0], byte_number);
    goto _OVER_;
}
for(index = 0; index < byte_number; index ++)
{
    pBuffer[index] = smbus_data.block[index + 1];
}

ret_val = 0;

_OVER_:
if(i2c_dev_fd >= 0)
{
    close(i2c_dev_fd);
}

return ret_val;

}

int write_8bit_i2c(int bus_index, unsigned char device_addr/8bits/, unsigned char register_addr, unsigned char *pBuffer, int byte_number)
{
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data smbus_data;
int ret_val = -1;
int i2c_dev_fd = -1;
int index = 0;

/**/
if(byte_number >= I2C_SMBUS_BLOCK_MAX)
{
    printf("standard_i2c_write ioctl Invalid parameter(%d)\n", byte_number);
    return -1;
}

i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
    printf("standard_i2c_write Standard_i2c_open Failed\n");
    goto _OVER_;
}

/*set address*/
ioctl(i2c_dev_fd, I2C_TENBIT, 0);
if(ioctl(i2c_dev_fd, I2C_SLAVE_FORCE, (device_addr) & 0x7f) < 0)
{
    perror("i2c ioctl:");
    printf("standard_i2c_write ioctl(I2C_SLAVE) Failed\n");
    goto _OVER_;
}

/**/
smbus_data.block[0] = byte_number;
for(index = 0; index < byte_number; index ++)
{
    smbus_data.block[index + 1] = pBuffer[index];
}
/**/
ioctl_data.read_write = I2C_SMBUS_WRITE;
ioctl_data.command = register_addr;
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
ioctl_data.data = &smbus_data;
/**/
if(ioctl(i2c_dev_fd, I2C_SMBUS, &ioctl_data) != 0)
{
    printf("standard_i2c_write ioctl(I2C_SMBUS) Failed(%d)\n", index);
    goto _OVER_;
}

ret_val = 0;

_OVER_:
if(i2c_dev_fd >= 0)
{
    close(i2c_dev_fd);
}

return ret_val;

}

#endif

int usage(char *pname)
{
printf(“%s i2c_ch <8/16> [value]\n”, pname);
return 0;
}

/* read ./iis 16 0x24 0x0111 /
/
write ./iis 16 0x24 0x0111 0x3 */

int main(int argc, char *argv)
{
unsigned char i2c_dev;
unsigned int i2c_reg;
unsigned char value[4];
unsigned int readvalue;
unsigned char reg_bit;
int i;
int i2c_channel;
if(argc < 3)
{
usage(argv[0]);
exit(1);
}

i2c_channel = strtoll(argv[1],NULL,0);
reg_bit=strtoll(argv[2], NULL, 0);
i2c_dev=strtoll(argv[3], NULL, 0);
i2c_reg=strtoll(argv[4], NULL, 0);

printf("reg_bit i2c_channel= %x,reg_bit=%x,i2c_dev=%x,i2c_reg=%x \n",i2c_channel,reg_bit,i2c_dev,i2c_reg);

if(argc == 5)
{
    if(16 == reg_bit){
        read_16bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0]);
    }else{
        read_8bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0], 1);
    }

    printf("read reg 0x%x value: 0x%x \n",i2c_reg,value[0]);
}
else if(argc == 6)
{
    value[0]=strtoll(argv[5], NULL, 0);

    if(16 == reg_bit){
        write_16bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0]);
    }else{
        write_8bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0], 1);
    }
    printf("write reg 0x%x value: 0x%x \n",i2c_reg,value[0]);
}

}

You have a check the power/clock and power down and reset pin is at right status before do the i2c access.

Hi,ShaneCCC:
I am sure that the sensor is working properly during the test, and the MIPI of the sensor can output the data.I want to confirm if i2cget, i2cset and i2cdump can be used to read a 16bit register address device?

I believe i2cget don’t support 16bit address. The failed ack maybe the address been cute as 8 bit address.